【问题标题】:Remove duplicates in an array without changing order of elements删除数组中的重复项而不更改元素的顺序
【发布时间】:2013-10-30 23:09:33
【问题描述】:

我有一个数组,比如List<Integer> 139, 127, 127, 139, 130

如何删除重复项并保持其顺序不变?即139, 127, 130

【问题讨论】:

  • 手动删除重复,这种情况下可以保持顺序。

标签: java arrays duplicates


【解决方案1】:

使用java.util.LinkedHashSet 的实例。

Set<Integer> set = new LinkedHashSet<>(list);

【讨论】:

  • 嗯...那是降级,我使用的是 Java 7 的菱形表示法。
  • 很抱歉,喝完咖啡后我会完全不同。
【解决方案2】:

有了这个单行:

yourList = new ArrayList<Integer>(new LinkedHashSet<Integer>(yourList))

【讨论】:

    【解决方案3】:

    没有LinkedHashSet 开销(使用HashSet 代替可见元素,这会稍微快一些):

    List<Integer> noDuplicates = list
            .stream()
            .distinct()
            .collect(Collectors.toList());
    

    请注意,订单由Stream.distinct() 合约保证:

    对于有序流,不同元素的选择是稳定的(对于 重复元素,该元素首先出现在遭遇战中 顺序被保留。)

    【讨论】:

      【解决方案4】:

      从您的列表中构造Set - “一个不包含重复元素的集合”:

      Set<Integer> yourSet = new HashSet<Integer>(yourList);
      

      并将其转换回您想要的任何内容。

      注意:如果要保持顺序,请改用LinkedHashSet

      【讨论】:

      • HashSet 是否保留插入顺序?
      • 您必须使用LinkedHashSet 来保留插入顺序。
      • 你需要一个 LinkedHashSet
      • 这不会保留订单 afak
      【解决方案5】:

      使用LinkedHashSet 删除重复并保持秩序。

      【讨论】:

        【解决方案6】:

        正如我无法推断的那样,您需要保留插入顺序,即完成 @Maroun Maroun 所写的内容,使用 set,但像 LinkedHashSet&lt;E&gt; whitch 这样的特殊实现完全可以满足您的需求。

        【讨论】:

          【解决方案7】:

          遍历数组(通过迭代器,而不是 foreach)并删除重复项。使用 set 查找重复项。

          遍历数组并将所有元素添加到LinkedHashSet,它不允许重复并保持元素的顺序。 然后清空数组,遍历集合并将每个元素添加到数组中。

          【讨论】:

            【解决方案8】:

            虽然将 ArrayList 转换为 HashSet 可以有效地删除重复项,但如果您需要保留插入顺序,我还是建议您使用此变体

            // list 是一些字符串列表

               Set<String> s = new LinkedHashSet<String>(list);
            

            然后,如果需要取回 List 引用,可以再次使用转换构造函数。

            【讨论】:

              【解决方案9】:

              有两种方式:

              1. 只创建具有唯一整数的新列表

                • (与Maroun Maroun回答相同)
                • 你可以用 2 个嵌套的 fors 来做到这一点,像这样 O(n.n/2):

                  List<int> src,dst;
                  // src is input list
                  // dst is output list
                  dst.allocate(src.num); // prepare size to avoid slowdowns by reallocations
                  dst.num=0;             // start from empty list
                  for (int i=0;i<src.num;i++)
                   {
                   int e=1;
                   for (int j=0;i<dst.num;i++)
                    if (src[i]==dst[j]) { e=0; break; }
                   if (e) dst.add(src[i]);
                   }
                  
              2. 您可以选择重复的项目并将其删除... O(2.n) 带有标记的删除

                • 这要快得多,但您需要整个 int 范围的内存表
                • 如果你使用数字 那么它将占用 BYTE cnt[10001]
                • 如果您使用数字 则需要 BYTE cnt[20002]
                • 对于这样的小范围是可以的,但如果您必须使用 32 位范围,则需要 4GB !!!
                • 使用位打包,每个值可以有 2 位,因此它只有 1GB,但这对我来说还是太多了
                • 现在如何检查重复性...

                  List<WORD> src;  // src is input list
                  BYTE cnt[65536]; // count usage for all used numbers
                  int i;
                  for (i=0;i<65536;i++) cnt[i]=0; // clear the count for all numbers
                  for (i=0;i<src.num;i++)         // compute the count for used numbers in the list  
                   if (cnt[src[i]]!=255) 
                    cnt[src[i]]++;
                  
                • 在此之后任何数字 i 都是重复的 if (cnt[i]>1)
                • 所以现在我们要删除重复的项目(除一个之外的所有项目)
                • 像这样改变cnt[]

                  for (i=0;i<65536;i++) if (cnt[i]>1) cnt[i]=1; else cnt[i]=0;
                  
                • 好的,现在是删除部分:

                  for (i=0;i<src.num;i++)         
                   if (cnt[src[i]]==1) cnt[src[i]]=2; // do not delete the first time
                    else if (cnt[src[i]]==2)          // but all the others yes
                     { 
                     src.del(i);
                     i--;                             // indexes in src changed after delete so recheck for the same index again
                     }
                  
              3. 您可以将这两种方法结合在一起

              4. 由于列表中的项目移位,从列表中删除项目很慢
                • 但可以通过向项目添加删除标志来加快速度
                • 设置标志而不是删除
                • 在所有要删除的项目都被标记后,只需立即删除下摆 O(n)

              PS。很抱歉使用非标准列表,但我认为如果不评论我,我认为代码是可以理解的,我会回复

              PPS。对于有符号值,不要忘记将地址移动一半!!!

              【讨论】:

                【解决方案10】:

                下面我给出了示例示例,该示例实现了一个通用函数以从 arraylist 中删除重复项并同时保持顺序。

                import java.util.*;
                public class Main {
                    //Generic function to remove duplicates in list and maintain order
                    private static <E> List<E> removeDuplicate(List<E> list) {
                        Set<E> array = new LinkedHashSet<E>();
                        array.addAll(list);
                        return new ArrayList<>(array);
                    }
                    public static void main(String[] args) {
                        //Print [2, 3, 5, 4]
                        System.out.println(removeDuplicate(Arrays.asList(2,2,3,5, 3, 4)));
                        //Print [AB, BC, CD]
                        System.out.println(removeDuplicate(Arrays.asList("AB","BC","CD","AB")));
                    }
                }
                

                【讨论】:

                  【解决方案11】:

                  方法 1:在 Python 中 => 使用集合和列表推导

                  a= [139, 127, 127, 139, 130]
                  
                  print(a)
                  seen =set()
                  aa = [ch  for ch in a if ch not in seen and not seen.add(ch)]
                  print(aa)
                  

                  方法二:

                  aa = list(set(a))
                  print(aa)
                  

                  在 Java 中:使用 Set 并创建一个新的 ArrayList

                  class t1 {
                      public static void main(String[] args) {
                  
                  int[] a = {139, 127, 127, 139, 130};
                  List<Integer> list1 = new ArrayList<>();
                  
                  Set<Integer> set = new LinkedHashSet<Integer>();
                  for( int ch  : a) {
                      if(!set.contains(ch)) {
                          set.add(ch);
                      }
                  
                  
                  }//for
                  set.forEach( (k) -> list1.add(k));
                  System.out.println(list1);
                  
                  }
                      }
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2018-03-18
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2017-06-04
                    • 2012-07-17
                    相关资源
                    最近更新 更多