如何使用 Java 中的辅助数组从列表中删除重复项?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12632167/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 09:38:04  来源:igfitidea点击:

How to remove duplicates from a list using an auxiliary array in Java?

javaarraysduplicatescounter

提问by user1702633

I am trying to remove duplicates from a list by creating a temporary array that stores the indices of where the duplicates are, and then copies off the original array into another temporary array while comparing the indices to the indices I have stored in my first temporary array.

我试图通过创建一个临时数组来从列表中删除重复项,该数组存储重复项所在位置的索引,然后将原始数组复制到另一个临时数组中,同时将索引与我存储在第一个临时数组中的索引进行比较.

public void removeDuplicates()
{
    double tempa [] = new double [items.length];
    int counter = 0;
    for ( int i = 0; i< numItems ; i++)
    {
        for(int j = i + 1; j < numItems; j++)
        {
            if(items[i] ==items[j])
            {
                tempa[counter] = j;
                counter++;

            }
        }
    }

    double tempb [] = new double [ items.length];
    int counter2 = 0;
    int j =0;
    for(int i = 0; i < numItems; i++)
    {
        if(i != tempa[j])
        {
            tempb[counter2] = items[i];
            counter2++;

        }
        else
        {
            j++;

        }
    }

    items = tempb;
    numItems = counter2;
}

and while the logic seems right, my compiler is giving me an arrayindexoutofbounds error at

虽然逻辑看起来是正确的,但我的编译器给了我一个 arrayindexoutofbounds 错误

tempa[counter] = j;

I don't understand how counter could grow to above the value of items.length, where is the logic flaw?

我不明白计数器如何增长到 items.length 的值以上,逻辑缺陷在哪里?

回答by Adam

You are making things quite difficult for yourself. Let Java do the heavy lifting for you. For example LinkedHashSet gives you uniqueness and retains insertion order. It will also be more efficient than comparing every value with every other value.

你让自己的事情变得很困难。让 Java 为您完成繁重的工作。例如 LinkedHashSet 为您提供唯一性并保留插入顺序。它也将比将每个值与每个其他值进行比较更有效。

double [] input = {1,2,3,3,4,4};
Set<Double> tmp = new LinkedHashSet<Double>();
for (Double each : input) {
    tmp.add(each);
}
double [] output = new double[tmp.size()];
int i = 0;
for (Double each : tmp) {
    output[i++] = each;
}
System.out.println(Arrays.toString(output));

回答by Dmitry Trifonov

Done for int arrays, but easily coud be converted to double.

为 int 数组完成,但很容易转换为 double。

1) If you do not careabout initial array elements order:

1)如果你不关心初始数组元素的顺序:

private static int[] withoutDuplicates(int[] a) {
    Arrays.sort(a);
    int hi = a.length - 1;
    int[] result = new int[a.length];
    int j = 0;
    for (int i = 0; i < hi; i++) {
        if (a[i] == a[i+1]) {
            continue;
        }
        result[j] = a[i];
        j++;            
    }
    result[j++] = a[hi];
    return Arrays.copyOf(result, j);
}

2) if you care about initial array elements order:

2)如果您关心初始数组元素顺序:

private static int[] withoutDuplicates2(int[] a) {
    HashSet<Integer> keys = new HashSet<Integer>();
    int[] result = new int[a.length];
    int j = 0;
    for (int i = 0 ; i < a.length; i++) {
        if (keys.add(a[i])) {
            result[j] = a[i];
            j++;
        }
    }
    return Arrays.copyOf(result, j);
}

3) If you do not careabout initial array elements order:

3)如果你不关心初始数组元素的顺序:

private static Object[] withoutDuplicates3(int[] a) {
    HashSet<Integer> keys = new HashSet<Integer>();
    for (int value : a) {
        keys.add(value);
    }
    return keys.toArray();
}

回答by srinivasbantu

import java.util.HashSet;

import sun.security.util.Length;


public class arrayduplication {
public static void main(String[] args) {
        int arr[]={1,5,1,2,5,2,10};
        TreeSet< Integer>set=new TreeSet<Integer>();
        for(int i=0;i<arr.length;i++){
            set.add(Integer.valueOf(arr[i]));
        }
        System.out.println(set);


    }

}

回答by Tim Bender

Imagine this was your input data:

想象一下这是您的输入数据:

Index: 0, 1, 2, 3, 4, 5, 6, 7, 8
Value: 1, 2, 3, 3, 3, 3, 3, 3, 3

Then according to your algorithm, tempawould need to be:

然后根据你的算法,tempa需要是:

Index: 0, 1, 2, 3, 4, 5, 6, 7, 8, ....Exception!!!
Value: 3, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 5, 6, 7, 8, 6, 7, 8, 7, 8, 8

Why do you have this problem? Because the first set of nested for loops does nothing to prevent you from trying to insert duplicates of the duplicate array indices!

你为什么会有这个问题?因为第一组嵌套的 for 循环不会阻止您尝试插入重复数组索引的重复项!

What is the best solution?

最好的解决方案是什么?

Use a Set!Sets guarantee that there are no duplicate entries in them. If you create a new Set and then add all of your array items to it, the Set will prune the duplicates. Then it is just a matter of going back from the Set to an array.

使用一套!集合保证其中没有重复的条目。如果您创建一个新 Set,然后将所有数组项添加到其中,则 Set 将修剪重复项。那么这只是从 Set 返回到数组的问题。

Alternatively, here is a very C-way of doing the same thing:

或者,这是做同样事情的一种非常 C 的方式:

//duplicates will be a truth table indicating which indices are duplicates.
//initially all values are set to false
boolean duplicates[] = new boolean[items.length];
for ( int i = 0; i< numItems ; i++) {
    if (!duplicates[i]) { //if i is not a known duplicate
        for(int j = i + 1; j < numItems; j++) {
            if(items[i] ==items[j]) {
                duplicates[j] = true; //mark j as a known duplicate
            }
        }
    }
}

I leave it to you to figure out how to finish.

我把它留给你来弄清楚如何完成。

回答by blearn

You have already used num_itemsto bound your loop. Use that variable to set your array size for tempa also.

你已经习惯num_items了你的循环。也可以使用该变量为 tempa 设置数组大小。

double tempa [] = new double [num_items];

回答by user1697575

Instead of doing it in array, you can simply use java.util.Set.

您可以简单地使用java.util.Set.

Here an example:

这里有一个例子:

public static void main(String[] args)
{
    Double[] values = new Double[]{ 1.0, 2.0, 2.0, 2.0, 3.0, 10.0, 10.0 };
    Set<Double> singleValues = new HashSet<Double>();

    for (Double value : values)
    {
        singleValues.add(value);
    }
    System.out.println("singleValues: "+singleValues);
    // now convert it into double array
    Double[] dValues = singleValues.toArray(new Double[]{});
}

回答by Matt

Here's another alternative without the use of sets, only primitive types:

这是不使用集合的另一种选择,仅使用原始类型:

public static double [] removeDuplicates(double arr[]) {
    double [] tempa = new double[arr.length];
    int uniqueCount = 0;
    for (int i=0;i<arr.length;i++) {
        boolean unique = true;
        for (int j=0;j<uniqueCount && unique;j++) {
            if (arr[i] == tempa[j]) {
                unique = false;
            }
        }
        if (unique) {
            tempa[uniqueCount++] = arr[i];
        }
    }

    return Arrays.copyOf(tempa,  uniqueCount);
}

It does require a temporary array of double objects on the way towards getting your actual result.

在获得实际结果的过程中,它确实需要一个临时的双对象数组。

回答by Kalla

You can use a set for removing multiples.

您可以使用集合来删除倍数。