Как удалить дубликаты из массива C#?

Я работал с string[] массив в C#, который возвращается из вызова функции. Я мог бы бросить в Generic коллекция, но мне было интересно, есть ли лучший способ сделать это, возможно, с помощью временного массива.

каков наилучший способ удаления дубликатов из массива C#?

20 ответов


для этого можно использовать запрос LINQ:

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

здесь HashSet подход:

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

к сожалению, это решение также требует .NET framework 3.5 или более поздней версии, поскольку HashSet не был добавлен до этой версии. Вы также можете использовать массив.Distinct (), что является особенностью LINQ.


Если вам нужно отсортировать его, вы можете реализовать сортировку, которая также удаляет дубликаты.

убивает двух зайцев одним выстрелом.


Это может зависеть от того, насколько вы хотите спроектировать решение - если массив никогда не будет таким большим, и вам не нужно сортировать список, вы можете попробовать что-то подобное следующему:

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

следующий проверенный и рабочий код удалит дубликаты из массива. Вы должны включить систему.Коллекции пространства имен.

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

вы можете обернуть это в функцию, если хотите.


- Это Вопросы спрашивает каждый раз. Теперь я сделал его кодирование.

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] = '';             
            }


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

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

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

Это O (n^2), что не имеет значения для короткого списка, который будет набит в комбо, но может быть быстро проблемой в большой коллекции.


добавьте все строки в словарь и получите свойство Keys после этого. Это приведет к созданию каждой уникальной строки, но не обязательно в том же порядке, в котором они были введены.

Если требуется, чтобы конечный результат имел тот же порядок, что и исходный ввод, при рассмотрении первого появления каждой строки используйте следующий алгоритм:

  1. есть список (окончательный вывод) и словарь (для проверки дубликатов)
  2. для каждого строка во входных данных, проверьте, существует ли она в словаре уже
  3. если нет, добавьте его как в словарь, так и в список

В конце список содержит первое появление каждой уникальной строки.

убедитесь, что вы учитываете такие вещи, как культура и такие при создании словаря, чтобы убедиться, что вы правильно обрабатываете дубликаты с ударением букв.


следующий фрагмент кода пытается удалить дубликаты из ArrayList, хотя это не является оптимальным решением. Мне задали этот вопрос во время интервью, чтобы удалить дубликаты через рекурсию, и без использования второго / temp arraylist:

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

возможно, hashset, которые не хранят повторяющиеся элементы и молча игнорируют запросы на добавление дубликаты.

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 + ",");
}

здесь O (n*n) подход, который использует O (1) пространство.

void removeDuplicates(char* strIn)
{
    int numDups = 0, prevIndex = 0;
    if(NULL != strIn && *strIn != '')
    {
        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] = '';
    }
}

на хэш / linq подходы выше - это то, что вы обычно используете в реальной жизни. Однако в интервью они обычно хотят ставить некоторые ограничения, например, постоянное пространство, которое исключает хэш или нет внутреннего api - что исключает использование LINQ.


примечание: не проверено!

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

может делать то, что вам нужно...

редактировать Аргх!!! опередил его Роб меньше чем за минуту!


протестировано ниже и работает. Что здорово, что он делает чувствительный к культуре поиск тоже

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


этот код 100% удаляет дубликаты значений из массива[как я использовал[i]].....Вы можете конвертировать его на любом языке OO..... :)

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

}

простое решение:

using System.Linq;
...

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

вы можете использовать этот код при работе с 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]);

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

Ниже приведена простая логика в java, вы дважды пересекаете элементы массива, и если вы видите какой-либо один и тот же элемент, вы назначаете ему ноль плюс вы не касаетесь индекса элемента, который вы сравниваете.

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

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