簡體   English   中英

如何使用Java中的輔助數組從列表中刪除重復項?

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

我試圖通過創建一個臨時數組來刪除列表中的重復項,該數組存儲重復項所在的索引,然后將原始數組復制到另一個臨時數組中,同時將索引與我存儲在第一個臨時數組中的索引進行比較。

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;
}

雖然邏輯看似正確,但我的編譯器在給我一個arrayindexoutofbounds錯誤

tempa[counter] = j;

我不明白計數器如何增長到items.length的值以上,邏輯缺陷在哪里?

你為自己制造的東西很難。 讓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));

完成int數組,但很容易轉換為double。

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)如果你關心初始數組元素的順序:

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)如果你不關心初始數組元素的順序:

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

想象一下這是你的輸入數據:

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

然后根據你的算法, 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

你為什么遇到這個問題? 因為第一組嵌套for循環不會阻止您嘗試插入重復數組索引的重復項!

什么是最好的解決方案?

使用套裝! 設置保證其中沒有重復的條目。 如果您創建一個新的Set然后將所有數組項添加到它,Set將修剪重復項。 然后,這只是從Set回到數組的問題。

或者,這是一個非常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
            }
        }
    }
}

我留給你弄清楚如何完成。

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);


    }

}

您已經使用num_items來綁定循環。 使用該變量也可以為tempa設置數組大小。

double tempa [] = new double [num_items];

您可以使用java.util.Set而不是在數組中執行此操作。

這是一個例子:

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[]{});
}

這是另一種不使用集合的替代方法,只有原始類型:

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);
}

它確實需要一個臨時的雙重對象數組來獲取實際結果。

您可以使用一組來刪除倍數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM