Bagaimana cara menghapus duplikat dari array C #?


209

Saya telah bekerja dengan string[]array di C # yang akan dikembalikan dari panggilan fungsi. Saya mungkin bisa melemparkan keGeneric koleksi, tapi saya bertanya-tanya apakah ada cara yang lebih baik untuk melakukannya, mungkin dengan menggunakan array temp.

Apa cara terbaik untuk menghapus duplikat dari array C #?


4
Gunakan metode ekstensi Berbeda.
kokos

Memang. Akan lebih menyenangkan ketika array sudah diurutkan - dalam hal ini dapat dilakukan di tempat dalam waktu O (n).
David Airapetyan

@ Vitim.us Tidak. Dalam kasus saya, ini bahkan bukan array, tetapi Daftar <string>. Saya menerima jawaban yang melakukan pekerjaan. Mungkin, itu mengejutkan karena harus melakukannya di atas kertas.
AngryHacker

Jawaban:


427

Anda bisa menggunakan kueri LINQ untuk melakukan ini:

int[] s = { 1, 2, 3, 3, 4};
int[] q = s.Distinct().ToArray();

22
Perhatikan bahwa Anda bisa menggunakan IEqualityComparer sebagai parameter, seperti .Distinct(StringComparer.OrdinalIgnoreCase)untuk mendapatkan serangkaian string case-insensitive berbeda.
justisb

Apakah Distinct menghormati urutan elemen asli?
asyrov

@asyrov: dari MSDN:The Distinct() method returns an unordered sequence that contains no duplicate values.
tigrou

52

Inilah pendekatan HashSet <string> :

public static string[] RemoveDuplicates(string[] s)
{
    HashSet<string> set = new HashSet<string>(s);
    string[] result = new string[set.Count];
    set.CopyTo(result);
    return result;
}

Sayangnya solusi ini juga memerlukan .NET framework 3.5 atau yang lebih baru karena HashSet tidak ditambahkan hingga versi itu. Anda juga bisa menggunakan array.Distinct () , yang merupakan fitur LINQ.


11
Ini mungkin tidak akan mempertahankan pesanan asli.
Hamish Grubijan

11

Kode yang diuji dan bekerja berikut ini akan menghapus duplikat dari array. Anda harus memasukkan namespace System.Collections.

string[] sArray = {"a", "b", "b", "c", "c", "d", "e", "f", "f"};
var sList = new ArrayList();

for (int i = 0; i < sArray.Length; i++) {
    if (sList.Contains(sArray[i]) == false) {
        sList.Add(sArray[i]);
    }
}

var sNew = sList.ToArray();

for (int i = 0; i < sNew.Length; i++) {
    Console.Write(sNew[i]);
}

Anda bisa membungkus ini menjadi fungsi jika Anda mau.


Ini tampaknya O (N ^ 2) ... Anda bisa menggunakan heap daripada ArrayList
Neil Chowdhury

10

Jika Anda perlu mengurutkannya, maka Anda bisa menerapkan jenis yang juga menghapus duplikat.

Membunuh dua burung dengan satu batu, lalu.


7
Bagaimana cara menyortir menghapus duplikat?
dan1

2
Siapa yang memilih ini? Ini bukan jawaban. "Bagaimana cara membuat panekuk?" "Masukkan beberapa bahan ke dalam busur dan aduk."
Quarkly

9

Ini mungkin tergantung pada seberapa banyak Anda ingin merekayasa solusi - jika array tidak akan pernah sebesar itu dan Anda tidak peduli tentang pengurutan daftar Anda mungkin ingin mencoba sesuatu yang mirip dengan yang berikut:

    public string[] RemoveDuplicates(string[] myList) {
        System.Collections.ArrayList newList = new System.Collections.ArrayList();

        foreach (string str in myList)
            if (!newList.Contains(str))
                newList.Add(str);
        return (string[])newList.ToArray(typeof(string));
    }

4
Anda harus menggunakan Daftar, bukan ArrayList.
Doug S

7

- Ini pertanyaan wawancara yang ditanyakan setiap saat. Sekarang saya melakukan pengkodeannya.

static void Main(string[] args)
{    
            int[] array = new int[] { 4, 8, 4, 1, 1, 4, 8 };            
            int numDups = 0, prevIndex = 0;

            for (int i = 0; i < array.Length; i++)
            {
                bool foundDup = false;
                for (int j = 0; j < i; j++)
                {
                    if (array[i] == array[j])
                    {
                        foundDup = true;
                        numDups++; // Increment means Count for Duplicate found in array.
                        break;
                    }                    
                }

                if (foundDup == false)
                {
                    array[prevIndex] = array[i];
                    prevIndex++;
                }
            }

            // Just Duplicate records replce by zero.
            for (int k = 1; k <= numDups; k++)
            {               
                array[array.Length - k] = '\0';             
            }


            Console.WriteLine("Console program for Remove duplicates from array.");
            Console.Read();
        }

3
Anda seharusnya tidak melakukan kompleksitas waktu O (n * 2) untuk pertanyaan ini.
dan1

2
Anda harus menggunakan jenis gabungan
Nick Gallimore

7
List<String> myStringList = new List<string>();
foreach (string s in myStringArray)
{
    if (!myStringList.Contains(s))
    {
        myStringList.Add(s);
    }
}

Ini adalah O (n ^ 2) , yang tidak masalah untuk daftar pendek yang akan dimasukkan ke dalam kombo, tetapi bisa dengan cepat menjadi masalah pada koleksi besar.


6
protected void Page_Load(object sender, EventArgs e)
{
    string a = "a;b;c;d;e;v";
    string[] b = a.Split(';');
    string[] c = b.Distinct().ToArray();

    if (b.Length != c.Length)
    {
        for (int i = 0; i < b.Length; i++)
        {
            try
            {
                if (b[i].ToString() != c[i].ToString())
                {
                    Response.Write("Found duplicate " + b[i].ToString());
                    return;
                }
            }
            catch (Exception ex)
            {
                Response.Write("Found duplicate " + b[i].ToString());
                return;
            }
        }              
    }
    else
    {
        Response.Write("No duplicate ");
    }
}

6

Berikut ini adalah pendekatan O (n * n) yang menggunakan ruang O (1) .

void removeDuplicates(char* strIn)
{
    int numDups = 0, prevIndex = 0;
    if(NULL != strIn && *strIn != '\0')
    {
        int len = strlen(strIn);
        for(int i = 0; i < len; i++)
        {
            bool foundDup = false;
            for(int j = 0; j < i; j++)
            {
                if(strIn[j] == strIn[i])
                {
                    foundDup = true;
                    numDups++;
                    break;
                }
            }

            if(foundDup == false)
            {
                strIn[prevIndex] = strIn[i];
                prevIndex++;
            }
        }

        strIn[len-numDups] = '\0';
    }
}

Pendekatan hash / linq di atas adalah apa yang biasanya Anda gunakan dalam kehidupan nyata. Namun dalam wawancara mereka biasanya ingin menempatkan beberapa kendala misalnya ruang konstan yang mengesampingkan hash atau tidak ada api internal - yang mengesampingkan menggunakan LINQ .


1
Bagaimana itu bisa menggunakan O (1) ruang, ketika Anda harus menyimpan seluruh daftar? Dengan memulai dengan jenis inplace, Anda dapat melakukan waktu O (nlogn) dan memori O (n), dengan kode yang jauh lebih sedikit.
Thomas Ahle

1
Apa yang membuat Anda berpikir itu menyimpan seluruh daftar? Memang melakukan di tempat. Dan meskipun bukan syarat dalam pertanyaan, kode saya mempertahankan urutan karakter dalam string asli. Penyortiran akan menghapus itu.
Sesh

1
Loop dalam ( strIn[j] == strIn[i]) akan membandingkan string dengan dirinya sendiri kecuali jika diperhitungkan dengan pernyataan if.
User3219

5

Tambahkan semua string ke kamus dan dapatkan properti Keys sesudahnya. Ini akan menghasilkan setiap string unik, tetapi tidak harus dalam urutan yang sama dengan input asli Anda.

Jika Anda mengharuskan hasil akhir memiliki urutan yang sama dengan input asli, saat Anda mempertimbangkan kemunculan pertama setiap string, gunakan algoritma berikut ini sebagai gantinya:

  1. Memiliki daftar (hasil akhir) dan kamus (untuk memeriksa duplikat)
  2. Untuk setiap string dalam input, periksa apakah sudah ada dalam kamus
  3. Jika tidak, tambahkan keduanya ke kamus dan ke daftar

Pada akhirnya, daftar berisi kejadian pertama dari setiap string unik.

Pastikan Anda mempertimbangkan hal-hal seperti budaya dan semacamnya saat menyusun kamus Anda, untuk memastikan Anda menangani duplikat dengan huruf beraksen dengan benar.


5

Sepotong kode berikut mencoba untuk menghapus duplikat dari ArrayList meskipun ini bukan solusi yang optimal. Saya ditanya pertanyaan ini selama wawancara untuk menghapus duplikat melalui rekursi, dan tanpa menggunakan daftar array temp / kedua:

private void RemoveDuplicate() 
{

ArrayList dataArray = new ArrayList(5);

            dataArray.Add("1");
            dataArray.Add("1");
            dataArray.Add("6");
            dataArray.Add("6");
            dataArray.Add("6");
            dataArray.Add("3");
            dataArray.Add("6");
            dataArray.Add("4");
            dataArray.Add("5");
            dataArray.Add("4");
            dataArray.Add("1");

            dataArray.Sort();

            GetDistinctArrayList(dataArray, 0);
}

private void GetDistinctArrayList(ArrayList arr, int idx)

{

            int count = 0;

            if (idx >= arr.Count) return;

            string val = arr[idx].ToString();
            foreach (String s in arr)
            {
                if (s.Equals(arr[idx]))
                {
                    count++;
                }
            }

            if (count > 1)
            {
                arr.Remove(val);
                GetDistinctArrayList(arr, idx);
            }
            else
            {
                idx += 1;
                GetDistinctArrayList(arr, idx);
            }
        }

5

Solusi sederhana:

using System.Linq;
...

public static int[] Distinct(int[] handles)
{
    return handles.ToList().Distinct().ToArray();
}

5

Mungkin hashset yang tidak menyimpan elemen duplikat dan diam-diam mengabaikan permintaan untuk menambahkan duplikat.

static void Main()
{
    string textWithDuplicates = "aaabbcccggg";     

    Console.WriteLine(textWithDuplicates.Count());  
    var letters = new HashSet<char>(textWithDuplicates);
    Console.WriteLine(letters.Count());

    foreach (char c in letters) Console.Write(c);
    Console.WriteLine("");

    int[] array = new int[] { 12, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2 };

    Console.WriteLine(array.Count());
    var distinctArray = new HashSet<int>(array);
    Console.WriteLine(distinctArray.Count());

    foreach (int i in distinctArray) Console.Write(i + ",");
}

4

CATATAN: TIDAK diuji!

string[] test(string[] myStringArray)
{
    List<String> myStringList = new List<string>();
    foreach (string s in myStringArray)
    {
        if (!myStringList.Contains(s))
        {
            myStringList.Add(s);
        }
    }
    return myStringList.ToString();
}

Dapat melakukan apa yang Anda butuhkan ...

EDIT Argh !!! dikalahkan dengan rob oleh kurang dari satu menit!


Rob tidak mengalahkanmu untuk apa pun. Dia menggunakan ArrayList, saat Anda menggunakan Daftar. Versi Anda lebih baik.
Doug S

4

Diuji di bawah & berhasil. Yang keren adalah ia melakukan pencarian yang sensitif terhadap budaya juga

class RemoveDuplicatesInString
{
    public static String RemoveDups(String origString)
    {
        String outString = null;
        int readIndex = 0;
        CompareInfo ci = CultureInfo.CurrentCulture.CompareInfo;


        if(String.IsNullOrEmpty(origString))
        {
            return outString;
        }

        foreach (var ch in origString)
        {
            if (readIndex == 0)
            {
                outString = String.Concat(ch);
                readIndex++;
                continue;
            }

            if (ci.IndexOf(origString, ch.ToString().ToLower(), 0, readIndex) == -1)
            {
                //Unique char as this char wasn't found earlier.
                outString = String.Concat(outString, ch);                   
            }

            readIndex++;

        }


        return outString;
    }


    static void Main(string[] args)
    {
        String inputString = "aAbcefc";
        String outputString;

        outputString = RemoveDups(inputString);

        Console.WriteLine(outputString);
    }

}

--AptSenSDET


4

Kode ini 100% menghapus nilai duplikat dari array [seperti yang saya gunakan [i]] ..... Anda dapat mengonversinya dalam bahasa OO apa pun ..... :)

for(int i=0;i<size;i++)
{
    for(int j=i+1;j<size;j++)
    {
        if(a[i] == a[j])
        {
            for(int k=j;k<size;k++)
            {
                 a[k]=a[k+1];
            }
            j--;
            size--;
        }
    }

}

4

Metode Ekstensi Umum:

public static IEnumerable<TSource> Distinct<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
{
    if (source == null)
        throw new ArgumentNullException(nameof(source));

    HashSet<TSource> set = new HashSet<TSource>(comparer);
    foreach (TSource item in source)
    {
        if (set.Add(item))
        {
            yield return item;
        }
    }
}

1

Anda dapat menggunakan kode ini saat bekerja dengan ArrayList

ArrayList arrayList;
//Add some Members :)
arrayList.Add("ali");
arrayList.Add("hadi");
arrayList.Add("ali");

//Remove duplicates from array
  for (int i = 0; i < arrayList.Count; i++)
    {
       for (int j = i + 1; j < arrayList.Count ; j++)
           if (arrayList[i].ToString() == arrayList[j].ToString())
                 arrayList.Remove(arrayList[j]);

1
public static int RemoveDuplicates(ref int[] array)
{
    int size = array.Length;

    // if 0 or 1, return 0 or 1:
    if (size  < 2) {
        return size;
    }

    int current = 0;
    for (int candidate = 1; candidate < size; ++candidate) {
        if (array[current] != array[candidate]) {
            array[++current] = array[candidate];
        }
    }

    // index to count conversion:
    return ++current;
}

0

Di bawah ini adalah logika sederhana di java Anda melewati elemen array dua kali dan jika Anda melihat elemen yang sama Anda menetapkan nol untuk itu ditambah Anda tidak menyentuh indeks elemen yang Anda bandingkan.

import java.util.*;
class removeDuplicate{
int [] y ;

public removeDuplicate(int[] array){
    y=array;

    for(int b=0;b<y.length;b++){
        int temp = y[b];
        for(int v=0;v<y.length;v++){
            if( b!=v && temp==y[v]){
                y[v]=0;
            }
        }
    }
}

0
  private static string[] distinct(string[] inputArray)
        {
            bool alreadyExists;
            string[] outputArray = new string[] {};

            for (int i = 0; i < inputArray.Length; i++)
            {
                alreadyExists = false;
                for (int j = 0; j < outputArray.Length; j++)
                {
                    if (inputArray[i] == outputArray[j])
                        alreadyExists = true;
                }
                        if (alreadyExists==false)
                        {
                            Array.Resize<string>(ref outputArray, outputArray.Length + 1);
                            outputArray[outputArray.Length-1] = inputArray[i];
                        }
            }
            return outputArray;
        }

1
tolong jelaskan jawaban Anda.
Badiparmagi

0
using System;
using System.Collections.Generic;
using System.Linq;


namespace Rextester
{
    public class Program
    {
        public static void Main(string[] args)
        {
             List<int> listofint1 = new List<int> { 4, 8, 4, 1, 1, 4, 8 };
           List<int> updatedlist= removeduplicate(listofint1);
            foreach(int num in updatedlist)
               Console.WriteLine(num);
        }


        public static List<int> removeduplicate(List<int> listofint)
         {
             List<int> listofintwithoutduplicate= new List<int>();


              foreach(var num in listofint)
                 {
                  if(!listofintwithoutduplicate.Any(p=>p==num))
                        {
                          listofintwithoutduplicate.Add(num);
                        }
                  }
             return listofintwithoutduplicate;
         }
    }



}

Ini adalah cara yang sangat tidak efisien untuk melakukan ini. Lihat jawaban lain untuk melihat apa yang mereka lakukan.
Wai Ha Lee

0
strINvalues = "1,1,2,2,3,3,4,4";
strINvalues = string.Join(",", strINvalues .Split(',').Distinct().ToArray());
Debug.Writeline(strINvalues);

Kkk Tidak yakin apakah ini guna-guna atau hanya kode yang indah

1 strINvalues ​​.Split (','). Distinct (). ToArray ()

2 string.Gabung (",", XXX);

1 Memisahkan array dan menggunakan Distinct [LINQ] untuk menghapus duplikat 2 Bergabung kembali tanpa duplikat.

Maaf saya tidak pernah membaca teks di StackOverFlow hanya kodenya. itu lebih masuk akal daripada teks;)


Jawaban khusus kode adalah jawaban berkualitas rendah. Tambahkan beberapa penjelasan mengapa ini berhasil.
Taslim Oseni

0
int size = a.Length;
        for (int i = 0; i < size; i++)
        {
            for (int j = i + 1; j < size; j++)
            {
                if (a[i] == a[j])
                {
                    for (int k = j; k < size; k++)
                    {
                        if (k != size - 1)
                        {
                            int temp = a[k];
                            a[k] = a[k + 1];
                            a[k + 1] = temp;

                        }
                    }
                    j--;
                    size--;
                }
            }
        }

1
Selamat datang di SO. Sementara cuplikan kode ini mungkin solusinya, termasuk penjelasan sangat membantu untuk meningkatkan kualitas posting Anda. Ingatlah bahwa Anda menjawab pertanyaan untuk pembaca di masa depan, dan orang-orang itu mungkin tidak tahu alasan untuk saran kode Anda.
alan.elkin

Sayangnya kode ini tidak menghapus apa pun, jadi tidak menghapus duplikat.
P_P

0

Jalan terbaik? Sulit dikatakan, pendekatan HashSet terlihat cepat, tetapi (tergantung pada data) menggunakan algoritma pengurutan (CountSort?) Dapat jauh lebih cepat.

using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
    static void Main()
    {
        Random r = new Random(0); int[] a, b = new int[1000000];
        for (int i = b.Length - 1; i >= 0; i--) b[i] = r.Next(b.Length);
        a = new int[b.Length]; Array.Copy(b, a, b.Length);
        a = dedup0(a); Console.WriteLine(a.Length);
        a = new int[b.Length]; Array.Copy(b, a, b.Length);
        var w = System.Diagnostics.Stopwatch.StartNew();
        a = dedup0(a); Console.WriteLine(w.Elapsed); Console.Read();
    }

    static int[] dedup0(int[] a)  // 48 ms  
    {
        return new HashSet<int>(a).ToArray();
    }

    static int[] dedup1(int[] a)  // 68 ms
    {
        Array.Sort(a); int i = 0, j = 1, k = a.Length; if (k < 2) return a;
        while (j < k) if (a[i] == a[j]) j++; else a[++i] = a[j++];
        Array.Resize(ref a, i + 1); return a;
    }

    static int[] dedup2(int[] a)  //  8 ms
    {
        var b = new byte[a.Length]; int c = 0;
        for (int i = 0; i < a.Length; i++) 
            if (b[a[i]] == 0) { b[a[i]] = 1; c++; }
        a = new int[c];
        for (int j = 0, i = 0; i < b.Length; i++) if (b[i] > 0) a[j++] = i;
        return a;
    }
}

Hampir cabang bebas. Bagaimana? Mode debug, Langkah Ke (F11) dengan array kecil: {1,3,1,1,0}

    static int[] dedupf(int[] a)  //  4 ms
    {
        if (a.Length < 2) return a;
        var b = new byte[a.Length]; int c = 0, bi, ai, i, j;
        for (i = 0; i < a.Length; i++)
        { ai = a[i]; bi = 1 ^ b[ai]; b[ai] |= (byte)bi; c += bi; }
        a = new int[c]; i = 0; while (b[i] == 0) i++; a[0] = i++;
        for (j = 0; i < b.Length; i++) a[j += bi = b[i]] += bi * i; return a;
    }

Solusi dengan dua loop bersarang mungkin membutuhkan waktu, terutama untuk array yang lebih besar.

    static int[] dedup(int[] a)
    {
        int i, j, k = a.Length - 1;
        for (i = 0; i < k; i++)
            for (j = i + 1; j <= k; j++) if (a[i] == a[j]) a[j--] = a[k--];
        Array.Resize(ref a, k + 1); return a;
    }
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.