ระบุรายการที่ซ้ำกันในรายการ


120

ฉันมีรายการประเภทจำนวนเต็มเช่น:

[1, 1, 2, 3, 3, 3]

ฉันต้องการวิธีการส่งคืนรายการที่ซ้ำกันทั้งหมดเช่น:

[1, 3]

วิธีที่ดีที่สุดในการทำคืออะไร?


2
รายการอินพุตรับประกันว่าจะเรียงลำดับ (ตามตัวอย่าง) หรือไม่
NPE

7
จัดเรียงรายการจากนั้นดำเนินการโดยรักษาค่าปัจจุบันและค่าก่อนหน้า ถ้าปัจจุบัน == ก่อนหน้านี้คุณมีรายการที่ซ้ำกัน
mcfinnigan

ไม่จำเป็นต้องเรียงลำดับรายการ
สดที่สุด

คำตอบ:


183

วิธีการaddของSetผลตอบแทนบูลไม่ว่าจะเป็นค่าที่มีอยู่แล้ว (จริงถ้ามันไม่ได้อยู่ที่เป็นเท็จถ้ามีอยู่แล้วให้ดูเอกสารชุด )

ดังนั้นเพียงแค่วนซ้ำค่าทั้งหมด:

public Set<Integer> findDuplicates(List<Integer> listContainingDuplicates)
{ 
  final Set<Integer> setToReturn = new HashSet<>(); 
  final Set<Integer> set1 = new HashSet<>();

  for (Integer yourInt : listContainingDuplicates)
  {
   if (!set1.add(yourInt))
   {
    setToReturn.add(yourInt);
   }
  }
  return setToReturn;
}

1
ทำไมคุณถึง setToReturn? คุณไม่สามารถใช้ set1.add (yourInt) และส่งคืน set1 ได้หรือไม่?
ฟิลิป

3
ใช่แน่นอน แต่เมื่อมีการแสดงองค์ประกอบเพียงครั้งเดียวในรายการที่ระบุองค์ประกอบจะถูกเพิ่มเข้าไปด้วย ดูตัวอย่างในคำถาม: วิธีแก้ปัญหาของฉันจะคืนค่า [1,3] เนื่องจากหมายเลข 2 ถูกแทรกใน set1 แต่ไม่อยู่ใน setToReturn โซลูชันของคุณจะคืนค่า [1,2,3] (ซึ่งไม่ใช่ข้อกำหนด)
leifg

1
ฉันขอแนะนำให้คุณใช้for (Integer yourIntเพื่อหลีกเลี่ยงการชกมวยและการแกะกล่องโดยไม่จำเป็นโดยเฉพาะอย่างยิ่งเนื่องจากข้อมูลของคุณมีIntegers อยู่แล้ว
Hosam Aly

1
@JonasThelemann ความคิดทั้งหมดของชุดคือไม่สามารถมีรายการที่ซ้ำกันได้ ดังนั้น: ไม่ว่าคุณจะเพิ่ม 3 บ่อยแค่ไหนมันก็จะจบลงเพียงครั้งเดียวเสมอ
leifg

1
อย่างไรก็ตามในกรณีที่HashSetคุณต้องพิจารณาโหลดแฟกเตอร์เช่นเมื่อคุณระบุความจุเริ่มต้น100เนื่องจากคุณต้องการเพิ่มจำนวนองค์ประกอบนั้นจะถูกปัดเศษเป็นกำลังถัดไปของ 2 ( 128) ซึ่งหมายความว่า ด้วยค่าเริ่มต้นของปัจจัยการโหลด0.75fเกณฑ์การปรับขนาดจะเป็น96ดังนั้นจะมีการปรับขนาดก่อนที่คุณจะเพิ่ม100องค์ประกอบ โชคดีที่การปรับขนาดไม่ได้มีราคาแพงอีกต่อไป ด้วย JRE ที่เป็นปัจจุบันการปรับขนาดจะไม่ได้ทำการรีแฮชอีกต่อไปองค์ประกอบจะได้รับการกระจายระหว่างตำแหน่งผลลัพธ์ที่เป็นไปได้ทั้งสองตามบิตที่เกี่ยวข้อง
Holger

50

ฉันต้องการวิธีแก้ปัญหานี้เช่นกัน ฉันใช้วิธีแก้ปัญหาของ leifg และทำให้เป็นแบบทั่วไป

private <T> Set<T> findDuplicates(Collection<T> collection) {

    Set<T> duplicates = new LinkedHashSet<>();
    Set<T> uniques = new HashSet<>();

    for(T t : collection) {
        if(!uniques.add(t)) {
            duplicates.add(t);
        }
    }

    return duplicates;
}

1
ฉันรู้ว่านี่คือ 3 ปีต่อมา แต่ทำไม LinkedHashedSet นั่นคือทำไมคุณถึงสนใจคำสั่งซื้อ
Ahmad Ragab

4
@AhmadRagab คุณพูดถูก LinkedHashSet ไม่จำเป็นเว้นแต่คุณจะสนใจเกี่ยวกับลำดับที่พบรายการที่ซ้ำกัน (ซึ่งฉันคิดว่าฉันทำในเวลานั้น)
John Strickler

ขอบคุณสำหรับการติดตาม!
Ahmad Ragab

หากคุณมีข้อมูลอินพุตจำนวนมากจนคุณต้องการใช้โซลูชันที่เหมาะสมที่สุดนี้ (แทนที่จะจัดเรียงอินพุต) คุณจะต้องจัดสรรขนาดของวัตถุ HashSet () ไว้ล่วงหน้าด้วย หากไม่มีการจัดสรรล่วงหน้าคุณจะไม่ได้รับ O (1) เวลาแทรกเมื่อแทรกลงใน HashSet () เนื่องจากอาร์เรย์แฮชภายในได้รับการปรับขนาดซ้ำ ๆ จากนั้นเม็ดมีดจะเฉลี่ยเป็นเวลา O (log N) ซึ่งหมายความว่าการประมวลผล N รายการทั้งหมดจะกลายเป็น O (N log N) เมื่อเป็น O (N)
johnstosh

39

ฉันใช้โซลูชันของ John Strickler และปรับปรุงใหม่เพื่อใช้สตรีม API ที่แนะนำใน JDK8:

private <T> Set<T> findDuplicates(Collection<T> collection) {
    Set<T> uniques = new HashSet<>();
    return collection.stream()
        .filter(e -> !uniques.add(e))
        .collect(Collectors.toSet());
}

3
นี่มันอ่านยากใช่ไหม คุณกำลังทำผลข้างเคียงในการดำเนินการสตรีมทำให้ยากที่จะให้เหตุผล แต่นั่นเป็นเพียงแค่ฉันคิดสไตล์การใช้งาน มันกระชับและอาจเป็นวิธีที่สั้นที่สุดแม้ว่า;)
froginvasion

สำหรับรายการขนาดใหญ่คุณสามารถดำเนินการนี้พร้อมกันในหลายเธรดได้หรือไม่?
johnstosh

@froginvasion วิธีการที่สร้างขึ้นในdistinct()นั้นยังเป็นสถานะ ไม่สามารถคิดถึงการดำเนินการที่แตกต่างอย่างมีประสิทธิภาพ (O (n)) ซึ่งไม่ได้ระบุสถานะ
wilmol

18

นี่คือวิธีแก้ปัญหาโดยใช้ Streams กับ Java 8

// lets assume the original list is filled with {1,1,2,3,6,3,8,7}
List<String> original = new ArrayList<>();
List<String> result = new ArrayList<>();

คุณเพียงแค่ดูว่าความถี่ของวัตถุนี้มากกว่าหนึ่งครั้งในรายการของคุณหรือไม่ จากนั้นเรียก. discinct () เพื่อให้มีเฉพาะองค์ประกอบที่ไม่ซ้ำกันในผลลัพธ์ของคุณ

result = original.stream()
    .filter(e -> Collections.frequency(original, e) > 1)
    .distinct()
    .collect(Collectors.toList());
// returns {1,3}
// returns only numbers which occur more than once

result = original.stream()
    .filter(e -> Collections.frequency(original, e) == 1)
    .collect(Collectors.toList());
// returns {2,6,8,7}
// returns numbers which occur only once

result = original.stream()
    .distinct()
    .collect(Collectors.toList());
// returns {1,2,3,6,8,7}
// returns the list without duplicates

1
นี้เป็นสิ่งที่ดีในแง่ของการอ่าน แต่มันเป็นเรื่องจริงที่ไม่ดีสำหรับการทำงาน Collections::frequencyคือ O (n) ต้องผ่านคอลเลคชันทั้งหมดเพื่อค้นหาความถี่ของไอเท็ม O(n^2)และเรากำลังเรียกร้องครั้งนี้ครั้งเดียวสำหรับทุกรายการในคอลเลกชันซึ่งจะทำให้ตัวอย่างเหล่านี้ คุณจะสังเกตเห็นความแตกต่างในคอลเลกชันที่มีองค์ประกอบมากกว่าหนึ่งกลุ่ม ฉันไม่เคยใช้สิ่งนี้ในรหัสจริง
Pawan

14

โซลูชันฐาน java 8:

List duplicates =    
list.stream().collect(Collectors.groupingBy(Function.identity()))
    .entrySet()
    .stream()
    .filter(e -> e.getValue().size() > 1)
    .map(Map.Entry::getKey)
    .collect(Collectors.toList());

รายการอินพุตถูกเปลี่ยนรูปแบบเป็นแผนที่ (จัดกลุ่มตามค่าเดียวกัน) จากนั้นค่าของแผนที่ที่มีค่าเฉพาะจะถูก "ลบ" จากนั้นแมปโดยใช้คีย์จากนั้นรายชื่อของรายการจะถูกเปลี่ยนเป็น List
بلالالمصمودي

โซลูชันที่สวยงามและรวดเร็วสามารถปรับเปลี่ยนได้โดยตรงในการกรองเฉพาะผู้ที่ได้รับสินค้า
arberg

11
int[] nums =  new int[] {1, 1, 2, 3, 3, 3};
Arrays.sort(nums);
for (int i = 0; i < nums.length-1; i++) {

    if (nums[i] == nums[i+1]) {
        System.out.println("duplicate item "+nums[i+1]+" at Location"+(i+1) );
    }

}

เห็นได้ชัดว่าคุณสามารถทำอะไรก็ได้ที่คุณต้องการ (เช่นใส่ชุดเพื่อรับรายการค่าที่ซ้ำกัน) แทนที่จะพิมพ์ ... นอกจากนี้ยังมีประโยชน์ในการบันทึกตำแหน่งของรายการที่ซ้ำกันด้วย


7

ใช้ Guava บน Java 8

private Set<Integer> findDuplicates(List<Integer> input) {
    // Linked* preserves insertion order so the returned Sets iteration order is somewhat like the original list
    LinkedHashMultiset<Integer> duplicates = LinkedHashMultiset.create(input);

    // Remove all entries with a count of 1
    duplicates.entrySet().removeIf(entry -> entry.getCount() == 1);

    return duplicates.elementSet();
}

7

สิ่งนี้ยังใช้งานได้:

public static Set<Integer> findDuplicates(List<Integer> input) {
    List<Integer> copy = new ArrayList<Integer>(input);
    for (Integer value : new HashSet<Integer>(input)) {
        copy.remove(value);
    }
    return new HashSet<Integer>(copy);
}

ใช้งานได้ แต่ค่อนข้างช้าเนื่องจากการเรียก remove () ในรายการอาร์เรย์เป็นการค้นหาเชิงเส้น
johnstosh

จริง โปรดทราบว่าหากข้อมูลที่คุณป้อนมีรายการที่ซ้ำกันจำนวนมากการตีประสิทธิภาพจะน้อยกว่าหากมีเพียงไม่กี่รายการ
Adriaan Koster

6

คุณสามารถใช้สิ่งนี้:

List<Integer> newList = new ArrayList<Integer>();
for(int i : yourOldList)
{
    yourOldList.remove(i);
    if(yourOldList.contains(i) && !newList.contains(i)) newList.add(i);
}

2
การใช้รายการที่นี่ไม่ได้ผลมาก
Alexander Farber

2
และอย่าให้ฉันเริ่มใช้intเป็นประเภทตัวแปรที่นี่ หมายความว่าสำหรับการวนซ้ำทุก ๆ ครั้งจำนวนเต็มจะถูกแกะกล่องหนึ่งครั้งและ int จะถูกใส่กล่องสี่ครั้ง!
Sean Patrick Floyd

1
ฉันคิดว่าคุณสามารถรับ ConcurrentModificationException ได้อย่างง่ายดายเมื่อพยายามลบองค์ประกอบออกจากรายการในขณะที่ทำซ้ำ
Jad B.

1
นี่คือ 100% ConcurrentModificationException เนื่องจากคุณทำซ้ำในรายการและคุณลบองค์ประกอบได้ทันที
theo231022

5

Lambas อาจเป็นทางออก

Integer[] nums =  new Integer[] {1, 1, 2, 3, 3, 3};
List<Integer> list = Arrays.asList(nums);

List<Integer> dps = list.stream().distinct().filter(entry -> Collections.frequency(list, entry) > 1).collect(Collectors.toList());

1
ใช้งานได้ แต่เรียกใช้ Collections.frequency สำหรับแต่ละรายการจึงทำงานได้ช้า
arberg

4

ใช้ MultiMap เพื่อจัดเก็บแต่ละค่าเป็นชุดคีย์ / ค่า จากนั้นทำซ้ำตามคีย์และค้นหาคีย์ที่มีหลายค่า


3

หากคุณใช้Eclipse Collectionsสิ่งนี้จะได้ผล:

MutableList<Integer> list = Lists.mutable.with(1, 1, 2, 3, 3, 3);
Set<Integer> dupes = list.toBag().selectByOccurrences(i -> i > 1).toSet();
Assert.assertEquals(Sets.mutable.with(1, 3), dupes);

อัปเดต:ณ Eclipse Collections 9.2 คุณสามารถใช้งานได้แล้วselectDuplicates

MutableList<Integer> list = Lists.mutable.with(1, 1, 2, 3, 3, 3);
Set<Integer> dupes = list.toBag().selectDuplicates().toSet();
Assert.assertEquals(Sets.mutable.with(1, 3), dupes);

คุณยังสามารถใช้คอลเลกชันดั้งเดิมเพื่อทำสิ่งนี้ให้สำเร็จ:

IntList list = IntLists.mutable.with(1, 1, 2, 3, 3, 3);
IntSet dupes = list.toBag().selectDuplicates().toSet();
Assert.assertEquals(IntSets.mutable.with(1, 3), dupes);

หมายเหตุ:ฉันเป็นผู้กำหนดค่า Eclipse Collections


2
public class practicese {
       public static void main(String[] args) {   

           List<Integer> listOf = new ArrayList<Integer>();
           listOf.add(3);
           listOf.add(1);
           listOf.add(2);
           listOf.add(3);
           listOf.add(3);
           listOf.add(2);
           listOf.add(1);

           List<Integer> tempList = new ArrayList<Integer>();
           for(Integer obj:listOf){
                if(!tempList.contains(obj)){
                    tempList.add(obj);

                }
            }
            System.out.println(tempList);

    }

}

ฉันชอบคำตอบนี้เพียงแค่ต้องเพิ่มคำตอบอื่นเพื่อบันทึกรายการที่ซ้ำกันในรายการอื่น ขอบคุณ
Tiago Machado

2

คล้ายกับคำตอบบางส่วนที่นี่ แต่ถ้าคุณต้องการค้นหารายการที่ซ้ำกันตามคุณสมบัติบางอย่าง:

  public static <T, R> Set<R> findDuplicates(Collection<? extends T> collection, Function<? super T, ? extends R> mapper) {
    Set<R> uniques = new HashSet<>();
    return collection.stream()
        .map(mapper)
        .filter(e -> !uniques.add(e))
        .collect(toSet());
  }

1

สร้างMap<Integer,Integer>รายการวนซ้ำหากองค์ประกอบอยู่ในแผนที่เพิ่มค่าหรือเพิ่มลงในแผนที่โดยใช้ key = 1 วน
ซ้ำแผนที่และเพิ่มรายการองค์ประกอบทั้งหมดด้วยคีย์> = 2

public static void main(String[] args) {
        List<Integer> list = new LinkedList<Integer>();
        list.add(1);
        list.add(1);
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(3);
        Map<Integer,Integer> map = new HashMap<Integer, Integer>();
        for (Integer x : list) { 
            Integer val = map.get(x);
            if (val == null) { 
                map.put(x,1);
            } else {
                map.remove(x);
                map.put(x,val+1);
            }
        }
        List<Integer> result = new LinkedList<Integer>();
        for (Entry<Integer, Integer> entry : map.entrySet()) {
            if (entry.getValue() > 1) {
                result.add(entry.getKey());
            }
        }
        for (Integer x : result) { 
            System.out.println(x);
        }

    }

นี่คือสิ่งที่ดีงาม เป็นทางออกที่ดีที่สุดหากคุณต้องการทราบว่ามีรายการซ้ำกันกี่รายการ หมายเหตุบางประการ: (1) คุณไม่จำเป็นต้องเรียกลบ () ก่อนทำการใส่ () (2) คุณสามารถตั้งค่า LinkedList จากอาร์เรย์แทนที่จะใช้การเรียก add () ซ้ำ (3) เมื่อ val! = null คุณสามารถเพิ่ม x ในผลลัพธ์ได้ทันที ผลลัพธ์อาจเป็นชุดหรือรายการขึ้นอยู่กับว่าคุณต้องการนับจำนวนรายการที่ซ้ำกัน
johnstosh

1

คำตอบยอดนิยมในเวอร์ชันที่ได้รับการยืนยันขนาดกะทัดรัดนอกจากนี้ยังเพิ่มการตรวจสอบว่างและขนาดชุดที่จัดสรรไว้ล่วงหน้า:

public static final <T> Set<T> findDuplicates(final List<T> listWhichMayHaveDuplicates) {
    final Set<T> duplicates = new HashSet<>();
    final int listSize = listWhichMayHaveDuplicates.size();
    if (listSize > 0) {
      final Set<T> tempSet = new HashSet<>(listSize);
      for (final T element : listWhichMayHaveDuplicates) {
        if (!tempSet.add(element)) {
          duplicates.add(element);
        }
      }
    }
    return duplicates;
  }

คุณต้องการเช็คศูนย์หรือไม่? HashSet ใหม่ <> (0) จะส่งคืนชุดว่างที่เหมาะสมหรือไม่
johnstosh

@johnstosh รหัสนี้อาจทำให้ง่ายขึ้น แต่การตรวจสอบศูนย์อนุญาตให้เริ่มต้นtempSetด้วยlistSizeเมื่อจำเป็นเท่านั้น นี่เป็นการเพิ่มประสิทธิภาพเล็กน้อย แต่ฉันชอบ
Christophe Roussy

1

ฉันรับคำตอบของเซบาสเตียนและเพิ่ม keyExtractor เข้าไป -

    private <U, T> Set<T> findDuplicates(Collection<T> collection, Function<? super T,? extends U> keyExtractor) {
        Map<U, T> uniques = new HashMap<>(); // maps unique keys to corresponding values
        return collection.stream()
            .filter(e -> uniques.put(keyExtractor.apply(e), e) != null)
            .collect(Collectors.toSet());
    }

1

ทางเลือกที่ปลอดภัยต่อเธรดคือ:

/**
 * Returns all duplicates that are in the list as a new {@link Set} thread-safe.
 * <p>
 * Usually the Set will contain only the last duplicate, however the decision
 * what elements are equal depends on the implementation of the {@link List}. An
 * exotic implementation of {@link List} might decide two elements are "equal",
 * in this case multiple duplicates might be returned.
 * 
 * @param <X>  The type of element to compare.
 * @param list The list that contains the elements, never <code>null</code>.
 * @return A set of all duplicates in the list. Returns only the last duplicate.
 */
public <X extends Object> Set<X> findDuplicates(List<X> list) {
    Set<X> dups = new LinkedHashSet<>(list.size());
    synchronized (list) {
        for (X x : list) {
            if (list.indexOf(x) != list.lastIndexOf(x)) {
                dups.add(x);
            }
        }
    }
    return dups;
}

0

ลองทำเช่นนี้เพื่อค้นหารายการที่ซ้ำกันในรายการ:

ArrayList<String> arrayList1 = new ArrayList<String>(); 

arrayList1.add("A"); 
arrayList1.add("A"); 
arrayList1.add("B"); 
arrayList1.add("B"); 
arrayList1.add("B"); 
arrayList1.add("C"); 

for (int x=0; x< arrayList1.size(); x++) 
{ 
System.out.println("arrayList1 :"+arrayList1.get(x)); 
} 
Set s=new TreeSet(); 
s.addAll(arrayList1); 
Iterator it=s.iterator(); 
while (it.hasNext()) 
{ 
System.out.println("Set :"+(String)it.next()); 
} 

ใช่สิ่งนี้พบชุด แต่ไม่พบรายการหรือชุดของรายการที่ซ้ำกัน
johnstosh

0

สิ่งนี้ควรใช้ได้กับการจัดเรียงและไม่เรียงลำดับ

public void testFindDuplicates() {

    List<Integer> list = new ArrayList<Integer>();
    list.add(1);
    list.add(1);
    list.add(2);
    list.add(3);
    list.add(3);
    list.add(3);

    Set<Integer> result = new HashSet<Integer>();
    int currentIndex = 0;
    for (Integer i : list) {
        if (!result.contains(i) && list.subList(currentIndex + 1, list.size()).contains(i)) {
            result.add(i);
        }
        currentIndex++;
    }
    assertEquals(2, result.size());
    assertTrue(result.contains(1));
    assertTrue(result.contains(3));
}

การโทรมี () ในรายการย่อยของ ArrayList มีราคาแพงเนื่องจากเป็นการค้นหาเชิงเส้น นี่ก็โอเคสำหรับ 10 รายการ แต่ไม่ใช่สำหรับ 10 ล้าน
johnstosh

0

นี่เป็นปัญหาที่เทคนิคการใช้งานมีความโดดเด่น ตัวอย่างเช่นโซลูชัน F # ต่อไปนี้มีทั้งความชัดเจนและข้อผิดพลาดน้อยกว่าโซลูชัน Java ที่จำเป็นที่ดีที่สุด (และฉันทำงานทุกวันกับทั้ง Java และ F #)

[1;1;2;3;3;3] 
|> Seq.countBy id 
|> Seq.choose (fun (key,count) -> if count > 1 then Some(key) else None)

แน่นอนคำถามนี้เกี่ยวกับ Java ดังนั้นคำแนะนำของฉันคือใช้ไลบรารีที่นำคุณสมบัติการทำงานมาสู่ Java ตัวอย่างเช่นสามารถแก้ไขได้โดยใช้ไลบรารีของฉันเองดังต่อไปนี้ (และมีอีกหลายอย่างที่ควรค่าแก่การดูด้วย):

Seq.of(1,1,2,3,3,3)
.groupBy(new Func1<Integer,Integer>() {
    public Integer call(Integer key) {
        return key;
    }
}).filter(new Predicate<Grouping<Integer,Integer>>() {
   public Boolean call(Grouping<Integer, Integer> grouping) {
        return grouping.getGrouping().count() > 1;
   }
}).map(new Func1<Grouping<Integer,Integer>,Integer>() {
    public Integer call(Grouping<Integer, Integer> grouping) {
        return grouping.getKey();
    }
});

แล้วคุณจะเห็นว่า Java ยังคงดูดซับการเขียนโปรแกรมเชิงฟังก์ชันอยู่มากเพียงใด ปัญหาง่ายๆเช่นนี้ยากมากที่จะแสดงสิ่งที่คุณต้องการใน Java
froginvasion

0
public class DuplicatesWithOutCollection {

    public static void main(String[] args) {

        int[] arr = new int[] { 2, 3, 4, 6, 6, 8, 10, 10, 10, 11, 12, 12 };

        boolean flag = false;
        int k = 1;
        while (k == 1) {

            arr = removeDuplicate(arr);
            flag = checkDuplicate(arr, flag);
            if (flag) {
                k = 1;
            } else {
                k = 0;
            }

        }

    }

    private static boolean checkDuplicate(int[] arr, boolean flag) {
        int i = 0;

        while (i < arr.length - 1) {

            if (arr[i] == arr[i + 1]) {

                flag = true;

            } else {
                flag = false;
            }
            i++;

        }

        return flag;
    }

    private static int[] removeDuplicate(int[] arr) {

        int i = 0, j = 0;
        int[] temp = new int[arr.length];
        while (i < arr.length - 1) {

            if (arr[i] == arr[i + 1]) {

                temp[j] = arr[i + 1];
                i = i + 2;

            } else {

                temp[j] = arr[i];
                i = i + 1;

                if (i == arr.length - 1) {
                    temp[j + 1] = arr[i + 1];
                    break;
                }

            }
            j++;

        }
        System.out.println();
        return temp;
    }

}

การใช้งานโดยไม่ใช้คลาส Collection แต่ต้องการการปรับปรุงเล็กน้อยในการวนรอบความช่วยเหลือของอาสาสมัครเป็นสิ่งที่น่าชื่นชมผลลัพธ์สำหรับด้านบนมีลักษณะดังนี้ -> 2 3 4 6 8 10 11 12
Samrat Roy

ในการดำเนินการนี้ในเวลาที่น้อยลงคุณต้องใช้โครงสร้างข้อมูลที่ใช้แฮชเพื่อติดตามข้อมูลที่ซ้ำกัน นั่นคือเหตุผลที่คุณเห็นโซลูชันอื่น ๆ โดยใช้ HashSet () ซึ่งมีอยู่ใน Java
johnstosh

@johnstosh ใช่ฉันรู้เกี่ยวกับเรื่องนี้ แต่ฉันคิดที่จะทำโดยไม่ใช้คอลเล็กชันนั่นคือเหตุผลที่ฉันพูดถึงในความคิดเห็นของฉันดังที่คุณเห็นฉันได้แสดงความคิดเห็นก่อนเดือนกุมภาพันธ์ 2017 [มีเทคนิคที่คุณไม่ต้องใช้คอลเลกชันเลย ด้วยความซับซ้อนของเวลาที่น้อยลง] geeksforgeeks.org/… . ฉันได้ลองใช้โปรแกรมนั้นโดยไม่ทราบแนวทางปฏิบัติของ DS & Algo คุณไม่จำเป็นต้องลงคะแนนให้ฉันสำหรับสิ่งนั้น.. ยังไงก็ตามขอบคุณ
Samrat Roy

0
import java.util.Scanner;

public class OnlyDuplicates {
    public static void main(String[] args) {
        System.out.print(" Enter a set of 10 numbers: ");
        int[] numbers = new int[10];
        Scanner input = new Scanner(System.in);
        for (int i = 0; i < numbers.length; i++) {
            numbers[i] = input.nextInt();
        }
        numbers = onlyDuplicates(numbers);
        System.out.print(" The numbers are: ");
        for (int i = 0; i < numbers.length; i++) {
            System.out.print(numbers[i] + "");
        }
    }

    public static int[] onlyDuplicates(int[] list) {
        boolean flag = true;
        int[] array = new int[0];
        array = add2Array(array, list[0]);
        for (int i = 0; i < list.length; i++) {
            for (int j = 0; j < array.length; j++) {
                if (list[i] == array[j]) {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                array = add2Array(array, list[i]);
            }
            flag = true;
        }
        return array;
    }
    // Copy numbers1 to numbers2
    // If the length of numbers2 is less then numbers2, return false
    public static boolean copyArray(int[] source, int[] dest) {
        if (source.length > dest.length) {
            return false;
        }

        for (int i = 0; i < source.length; i++) {
            dest[i] = source[i];
        }
        return true;
    }
    // Increase array size by one and add integer to the end of the array
    public static int[] add2Array(int[] source, int data) {
        int[] dest = new int[source.length + 1];
        copyArray(source, dest);
        dest[source.length] = data;
        return dest;
    }
}

ฉันต้องเปลี่ยนอะไรเพื่อส่งคืนรายการที่ซ้ำกัน
Brenden

สิ่งนี้ควรถามเป็นคำถามใหม่
willaien

0

นี่เป็นวิธีที่ดีในการค้นหาค่าที่ซ้ำกันโดยไม่ต้องใช้ Set

public static <T> List<T> findDuplicates(List<T> list){

List<T> nonDistinctElements = new ArrayList<>();

  for(T s : list)
    if(list.indexOf(s) != list.lastIndexOf(s))
      if(!nonDistinctElements.contains(s))
        nonDistinctElements.add(s);

  return nonDistinctElements;
}

และบอกว่าคุณต้องการวิธีที่ส่งคืนรายการที่แตกต่างกันเช่นหากคุณส่งรายการที่มีองค์ประกอบเกิดขึ้นมากกว่าหนึ่งครั้งคุณจะได้รับรายการที่มีองค์ประกอบที่แตกต่างกัน

public static <T> void distinctList(List<T> list){

List<T> nonDistinctElements = new ArrayList<>();
for(T s : list)
  if(list.indexOf(s) != list.lastIndexOf(s))
    nonDistinctElements.add(s);

for(T nonDistinctElement : nonDistinctElements)
  if(list.indexOf(nonDistinctElement) != list.lastIndexOf(nonDistinctElement))
    list.remove(nonDistinctElement);
}

0

และเวอร์ชันที่ใช้commons-collections CollectionUtils.getCardinalityMapวิธีการ:

final List<Integer> values = Arrays.asList(1, 1, 2, 3, 3, 3);
final Map<Integer, Integer> cardinalityMap = CollectionUtils.getCardinalityMap(values);
System.out.println(cardinalityMap
            .entrySet()
            .stream().filter(e -> e.getValue() > 1)
            .map(e -> e.getKey())
            .collect(Collectors.toList()));

`` `


0

รหัสนี้เป็นอย่างไร -

public static void main(String[] args) {

    //Lets say we have a elements in array
    int[] a = {13,65,13,67,88,65,88,23,65,88,92};

    List<Integer> ls1 = new ArrayList<>();
    List<Integer> ls2 = new ArrayList<>();
    Set<Integer> ls3 = new TreeSet<>();

    //Adding each element of the array in the list      
    for(int i=0;i<a.length;i++) {
     {
    ls1.add(a[i]);
    }
    }

    //Iterating each element in the arrary
    for (Integer eachInt : ls1) {

    //If the list2 contains the iterating element, then add that into set<> (as this would be a duplicate element)
        if(ls2.contains(eachInt)) {
            ls3.add(eachInt);
        }
        else {ls2.add(eachInt);}

    }

    System.out.println("Elements in array or ls1"+ls1); 
    System.out.println("Duplicate Elements in Set ls3"+ls3);


}

0

ในกรณีที่ต้องการรวมทั้งรายการที่ซ้ำกันและไม่ซ้ำกัน โดยพื้นฐานแล้วคำตอบจะคล้ายกับคำตอบที่ถูกต้อง แต่แทนที่จะกลับจากถ้าไม่ใช่ส่วนหนึ่งคุณจะกลับส่วนอื่น

ใช้รหัสนี้ (เปลี่ยนเป็นประเภทที่คุณต้องการ)

public Set<String> findDup(List<String> Duplicates){
    Set<String> returning = new HashSet<>();
    Set<String> nonreturning = new HashSet<>();
    Set<String> setup = new HashSet<>();
    for(String i:Duplicates){
        if(!setup.add( i )){
            returning.add( i );
        }else{
            nonreturning.add( i );
        }
    }
    Toast.makeText( context,"hello set"+returning+nonreturning+" size"+nonreturning.size(),Toast.LENGTH_SHORT ).show();
    return nonreturning;
}

0

วิธีการทั่วไปเพิ่มเติมเป็นตัวแปรของhttps://stackoverflow.com/a/52296246

    /**
     * Returns a duplicated values found in given collection based on fieldClassifier
     *
     * @param collection given collection of elements
     * @param fieldClassifier field classifier which specifies element to check for duplicates(useful in complex objects).
     * @param <T> Type of element in collection
     * @param <K> Element which will be returned from method in fieldClassifier.
     * @return returns list of values that are duplocated.
     */
    public static <T, K> List<K> lookForDuplicates(List<T> collection, Function<? super T, ? extends K> fieldClassifier) {

        return collection.stream().collect(Collectors.groupingBy(fieldClassifier))
                         .entrySet()
                         .stream()
                         .filter(e -> e.getValue().size() > 1)
                         .map(Map.Entry::getKey)
                         .collect(Collectors.toList());
    }

-1

หากคุณทราบค่าสูงสุด (เช่น <10,000) คุณสามารถสละพื้นที่เพื่อความเร็วได้ ฉันจำชื่อที่แน่นอนของเทคนิคนี้ไม่ได้

รหัสหลอก:

//does not handle case when mem allocation fails 
//probably can be extended to unknown values /larger values .
maybe by sorting first
public List<int> GetDuplicates(int max)
{   
    //allocate and clear memory to 0/false
    bit[] buckets=new bit[max]
    memcpy(buckets,0,max);
    //find duplicates
    List<int> result=new List<int>();
    foreach(int val in List)
    {
        if (buckets[val])
        {
            result.add(value);
        }
        else
        {
            buckets[val]=1;
        }
    }
    return  result
}

ฉันคิดว่าคุณต้องการ "บูลีน" แทน "บิต" หรือไม่? คุณได้รันโค้ดของคุณก่อนโพสต์หรือไม่? นี่เป็นการเริ่มต้นที่ดี หากคุณดู HashSet () คุณจะเห็นว่ามันเป็นการใช้งาน 'ที่เก็บข้อมูล' ที่คุณต้องการ
johnstosh

-1

ลองทำสิ่งนี้:

ตัวอย่างถ้าค่ารายการคือ: [1, 2, 3, 4, 5, 6, 4, 3, 7, 8] รายการที่ซ้ำกัน [3, 4]

Collections.sort(list);
        List<Integer> dup = new ArrayList<>();
        for (int i = 0; i < list.size() - 1; i++) {
            if (list.get(i) == list.get(i + 1)) {
                if (!dup.contains(list.get(i + 1))) {
                    dup.add(list.get(i + 1));
                }
            }
        }
        System.out.println("duplicate item " + dup);

การเรียกใช้มี () ใน ArrayList () เป็นการดำเนินการที่มีราคาแพงดังนั้นคุณควรพิจารณาใช้ Set แทน คุณจะเห็นโซลูชันอื่น ๆ โดยใช้ HashSet () หรือเวอร์ชันที่เชื่อมโยงกัน
johnstosh
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.