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

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

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

13.08.2008 11:48:44
Используйте метод Distinct extension.
kokos 13.08.2008 12:02:34
В самом деле. Веселее, когда массив уже отсортирован - в этом случае это можно сделать на месте за O (n) раз.
David Airapetyan 2.03.2012 20:54:42
@ Vitim.us Нет. В моем случае это даже не массив, а List <string>. Я принимаю любой ответ, который делает работу. Возможно, это шок от необходимости делать это на бумаге.
AngryHacker 23.11.2012 00:05:44
23 ОТВЕТА
РЕШЕНИЕ

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

int[] s = { 1, 2, 3, 3, 4};
int[] q = s.Distinct().ToArray();
426
13.08.2008 12:03:05
Обратите внимание, что вы можете использовать IEqualityComparer в качестве параметра, например, .Distinct(StringComparer.OrdinalIgnoreCase)чтобы получить независимый от регистра отдельный набор строк.
justisb 13.10.2015 16:26:54
Отличительные награды оригинальный порядок элементов?
asyrov 24.02.2017 22:35:21
@asyrov: от MSDN:The Distinct() method returns an unordered sequence that contains no duplicate values.
tigrou 3.10.2018 10:13:45

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

Тогда убивает двух зайцев.

10
13.08.2008 11:51:52
Как сортировка удаляет дубликаты?
dan1 18.05.2016 00:46:30
Кто проголосовал за это? Это не ответ. "Как я могу сделать блины?" «Положите некоторые ингредиенты в лук и перемешайте».
Quarkly 4.04.2020 19:21:11

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

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

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

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

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

5
13.08.2008 12:53:33

Следующий проверенный и работающий код удалит дубликаты из массива. Вы должны включить пространство имен 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]);
}

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

11
13.08.2008 13:17:12
Похоже, это O (N ^ 2) ... Вы можете использовать кучу вместо ArrayList
Neil Chowdhury 8.03.2019 20:47:54

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

    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));
    }
9
13.08.2008 13:08:28
Вы должны использовать List вместо ArrayList.
Doug S 27.10.2012 05:05:52

ПРИМЕЧАНИЕ: НЕ проверено!

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

Можешь делать то, что тебе нужно ...

РЕДАКТИРОВАТЬ Argh !!! избили его грабителем менее чем за минуту!

4
13.08.2008 13:09:23
Роб ни к чему тебя не побил. Он использует ArrayList, а вы используете List. Ваша версия лучше.
Doug S 27.10.2012 05:05:11

Вот подход 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;
}

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

52
9.07.2013 18:00:17
Это, вероятно, не сохранит первоначальный порядок.
Hamish Grubijan 5.07.2011 15:07:19
List<String> myStringList = new List<string>();
foreach (string s in myStringArray)
{
    if (!myStringList.Contains(s))
    {
        myStringList.Add(s);
    }
}

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

7
7.06.2017 05:08:39

Вот подход O (n * n), который использует пространство 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';
    }
}

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

6
7.06.2017 05:08:23
Как он может использовать пробел O (1), когда вам нужно хранить весь список? Начав с сортировки по месту, вы можете использовать O (nlogn) время и O (n) память с гораздо меньшим количеством кода.
Thomas Ahle 27.04.2010 05:19:42
Что заставляет вас думать, что он хранит весь список? Это действительно делает на месте. И хотя это не условие в вопросе, мой код поддерживает порядок символов в исходной строке. Сортировка удалит это.
Sesh 30.04.2010 06:10:24
Внутренний цикл ( strIn[j] == strIn[i]) будет сравнивать строку с самим собой, если это не учитывается с помощью оператора if.
User3219 22.10.2018 19:46:58

Следующий фрагмент кода пытается удалить дубликаты из 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);
            }
        }
5
16.08.2011 23:08:36
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
14.02.2012 08:10:40

Может быть, 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 + ",");
}
5
7.06.2017 05:07:35

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

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
15.06.2013 07:18:39

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

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();
        }
7
3.07.2013 07:50:20
Вы не должны делать O (n * 2) время сложность для этого вопроса.
dan1 18.05.2016 00:50:14
Вы должны использовать сортировку слиянием
Nick Gallimore 13.06.2017 15:20:29

Этот код на 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--;
        }
    }

}
4
5.07.2014 14:14:47

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

using System.Linq;
...

public static int[] Distinct(int[] handles)
{
    return handles.ToList().Distinct().ToArray();
}
5
12.03.2015 21:40:51

Вы можете использовать этот код при работе с 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
12.04.2015 09:12:09
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;
}
1
25.03.2018 00:04:07

Ниже приведена простая логика в 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;
            }
        }
    }
}
0
16.11.2016 11:42:44
  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;
        }
0
30.11.2017 08:03:58
объясни свой ответ, пожалуйста.
Badiparmagi 30.11.2017 08:10:22

Общий метод расширения:

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;
        }
    }
}
3
13.10.2018 04:32:53
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;
         }
    }



}
0
25.04.2019 17:28:08
Это очень неэффективный способ сделать это. Посмотрите на другие ответы, чтобы увидеть, что они делают.
Wai Ha Lee 25.04.2019 17:55:03
strINvalues = "1,1,2,2,3,3,4,4";
strINvalues = string.Join(",", strINvalues .Split(',').Distinct().ToArray());
Debug.Writeline(strINvalues);

Kkk Не уверен, что это колдовство или просто красивый код

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

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

1 Разделение массива и использование Distinct [LINQ] для удаления дубликатов 2 Присоединение к нему без дубликатов.

Извините, я никогда не читал текст на StackOverFlow только код. это имеет больше смысла, чем текст;)

0
14.10.2019 12:04:32
Ответы только по коду - это некачественные ответы. Добавьте объяснение, почему это работает.
Taslim Oseni 3.10.2019 19:07:11