从ArrayList中删除重复项的算法

时间:2017-05-25 09:06:11

标签: java arrays arraylist duplicates

我有ArrayList<String>,其中包含以下内容:

2 #3#的 1 #0

1 #0#的 4 #1

9 #2#的 5 #0

4 #2#的 3 #2

1 #1#的 2 #1

输出:6个不同的数字。

我正在尝试编写一个算法来删除突出显示的数字的重复项,以便我可以使用计数器查看所有这些位置中总共有多少不同的数字。

我尝试过很多东西,包括以下一些内容:[Java使用循环从数组中删除重复项] [1],[Java - 删除ArrayList中的重复项] [2],[如何查找重复项中的第一个选项]在Java数组?] [3]等等。我花了至少5-10小时才试图弄清楚我做错了什么,但我不能,所以我转向你。

大多数时候,我在网上找到的解决方案似乎只是简单的工作,但不是我的情况。在其中,当我尝试打印不同的字符时,它总是返回错误的int数字。

我也尝试过,也尝试将每行数字分成不同的int Array[],然后比较,但它不会捕获所有不同的值。

在另一个例子中,我总共有5个不同的数字,因此我不断得到“4个不同”,所以我甚至尝试long n = ArrayList.stream().distinct().count(); 只是为了看我是否在做某事错了,但即便是这件事也回归了“4个不同”的数字。

我知道最简单的方法是使用SetMap,但我不希望这样。我想要一个算法。

编辑:

我尝试过的很多事情之一是:

for (int m = 0; m < (size-1); m++){
        for (int j = m + 1; j < size; j++){
            if (ArrayList.get(j).charAt(0) != ArrayList.get(m).charAt(0)){
                continue;
            }
            current++;
            ArrayList.remove(j).charAt(0);
            j--;
            size--;
        }
    }

有了这个,我必须使用另一个ArrayList.get().charAt(4)

EDIT2:

我找到了以下代码[here] [1],但在这种情况下如何实现?

public static <T> ArrayList<T> uniquefy(ArrayList<T> myList) {

    ArrayList <T> uniqueArrayList = new ArrayList<T>();
    for (int i = 0; i < myList.size(); i++){
        if (!uniqueArrayList.contains(myList.get(i))){
            uniqueArrayList.add(myList.get(i));
        }
    }

    return uniqueArrayList;
}

EDIT3: 我找到了一个可能的解决方案,但它给了我一个IndexOutOfBoundsException。 我已将数字 2,1,9,4,1 放入Array1,将 1,4,5,3,2 放入{{1} },但是当我尝试比较它们时,我得到了上面提到的错误。

Array2

w.com/questions/203984/how-do-i-remove-repeated-elements-from-arraylist?rq=1

4 个答案:

答案 0 :(得分:3)

算法比你想象的要简单得多:

  1. 将每个字符串转换为一对字符
  2. 将所有字符放入删除重复项的集合或流中
  3. 计算字符数。
  4. 这是一个完整的例子:

    import java.util.Arrays;
    import java.util.List;
    import java.util.stream.IntStream;
    
    public class Duplicates {
        public static void main(String[] args) {
            List<String> list = Arrays.asList("2#3#1#0",
                                              "1#0#4#1",
                                              "9#2#5#0",
                                              "4#2#3#2",
                                              "1#1#2#1");
            System.out.println(
                list.stream()
                    .flatMapToInt(s -> IntStream.of(s.charAt(0), s.charAt(4)))
                    .distinct()
                    .count());
        }
    }
    

    编辑:你似乎想要遵守荒谬的限制,因此既不使用Stream也不使用Set,这些完全有意义。这里的代码只使用列表,但基本上与上面的内容相同,但效率要低得多:

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    public class Duplicates {
        public static void main(String[] args) {
            List<String> list = Arrays.asList("2#3#1#0",
                                              "1#0#4#1",
                                              "9#2#5#0",
                                              "4#2#3#2",
                                              "1#1#2#1");
            List<Character> uniqueChars = new ArrayList<>();
            for (String s : list) {
                Character c0 = s.charAt(0);
                Character c4 = s.charAt(4);
    
                if (!uniqueChars.contains(c0)) {
                    uniqueChars.add(c0);
                }
                if (!uniqueChars.contains(c4)) {
                    uniqueChars.add(c4);
                }
            }
    
            System.out.println(uniqueChars.size());
        }
    }
    

答案 1 :(得分:2)

计算不同数量的突出显示位置并不困难。您可以使用称为频率数组的辅助数组来获得预期结果。

使用频率数组尝试这个简单的算法我认为它适用于您的情况:

       ArrayList<String> numlist=new ArrayList<String>();
       int freq[] = new int [10];
       numlist.add("2#3#1#0");
       numlist.add("1#0#4#1");
       numlist.add("9#2#5#0");
       numlist.add("4#2#3#2");
       numlist.add("1#1#2#1");
       for(int i = 0; i < numlist.size(); i++){
           String row = numlist.get(i);          
           int numValue1 = Character.getNumericValue(row.charAt(0));
           int numValue2 = Character.getNumericValue(row.charAt(4));
           freq[numValue1]++;
           freq[numValue2]++;          
       }
       int count = 0;
       for(int i = 0; i < 10; i++){
           if(freq[i] > 0){
               count++;
           }
       }
       System.out.println(count + " different numbers");

<强>输出

6 different numbers

答案 2 :(得分:1)

位掩码的另一个选项:

public static void main(String[] args) {
    List<String> arrayList = Arrays.asList("2#3#1#0", "1#0#4#1", "9#2#5#0", "4#2#3#2", "1#1#2#1");
    int mask = 0;
    for(String s : arrayList) { // Place the bits
        mask = mask | (1 << Character.getNumericValue(s.charAt(0))) | (1 << Character.getNumericValue(s.charAt(4)));
    }
    int counter = 0;
    for(int i = 0; i < 32; i++) { // count the bits
        counter += (mask & (1 << i)) == 1 << i ? 1 : 0;
    }
    System.out.println(counter);
}

输出:

6

这依赖于代码执行结束时的位掩码:

1000111110

这可能比大多数解决方案更快,因为它不依赖于传统的数据结构。

答案 3 :(得分:0)

嗯,一个好的做法总是将问题分成更小的部分

例如,一个好的设计将是一个包含这些成员的类:

  • digits:这是一个int数组的实例变量,用于包含每个数字重复的次数。它必须预先设定为允许的最大数字(我猜是 9 )。
  • differentDigits:是一个包含不同数字位数的实例变量。
  • processList:此方法将收到列表以进行浏览,并为每个项目调用processItem
  • processItem:此方法应接收项目字符串并根据指定的格式解析数字(例如,通过StringTokenizer),并为每个所需的数字调用storeDigit。< / LI>
  • storeDigit:此方法应接收一个int并使用它来索引实例数组digits,并递增索引位置。如果索引位置为0,则还应增加differentDigits