Korathu 2 Ответов: 6

Как проверить дубликаты в массив строк с#


Как проверить дубликаты в строковом массиве c#..Также покажите сообщение, если дубликат присутствует....

6 Ответов

Рейтинг:
45

Shmuel Zang

Вы можете использовать Отчетливый метод. Что-то вроде:


string[] myStrings = // ...

if (myStrings.Distinct().Count() != myStrings.Count())
{
    // Show message
}


Ian A Davidson

Хороший ответ. +5.

Himanshu Yadav

Но как преобразовать в массив, если строка похожа на "мы не являемся сотрудником, но мы приходим в таблицу сотрудников" без использования метода split (")...... пожалуйста, помогите мне

Shmuel Zang

Спасибо, Йен.

Рейтинг:
2

Naz_Firdouse

Вы можете использовать Distinct (), как упоминал Шмуэль.
Если вы хотите отобразить дублированные элементы , то можете использовать Linq

 string[] array = { "First", "Second", "Third", "First", "Third" }; 
var i= CheckforDuplicates(array);


public bool CheckforDuplicates(string[] array)
      {
          var duplicates = array
           .GroupBy(p => p)
           .Where(g => g.Count() > 1)
           .Select(g => g.Key);


          return (duplicates.Count() > 0);



      }


где переменная duplicates содержит список повторяющихся элементов


Korathu 2

Ни один не сработал ...

Naz_Firdouse

что случилось?
если переменная имеет значение true,это означает, что существует повторяющееся значение...
в чем тут проблема?

Рейтинг:
2

Matt T Heffron

Аналогично решению Наза:

private static int CountDuplicates(string[] array)
{
  HashSet<string> stringSet = new HashSet<string>();
  int numDups = 0;
  foreach (var item in array)
  {
    if (stringSet.Contains(item))
    {
      ++numDups;
    }
    else
    {
      stringSet.Add(item);
    }
  }
  return numDups;
}

// this returns an IEnumerable with both the strings and the repeat counts (might be useful for reporting...)
private static IEnumerable<KeyValuePair<string, int>> FindDuplicates(string[] array)
{
  Dictionary<string, int> stringSet = new Dictionary<string, int>();
  foreach (var item in array)
  {
    int count;
    if (stringSet.TryGetValue(item, out count))
    {
      stringSet[item] = count + 1;
    }
    else
    {
      stringSet[item] = 1;
    }
  }
  return stringSet.Where(p => p.Value > 1);
}

Время выполнения этого задания составляет O(n) в длину array.


aarnone2

На самом деле это порядок (N log N)

Операция stringSet.Contains имеет логарифмическую сложность N

Matt T Heffron

Нет. HashSet<t>.Contains() is O(1).
https://msdn.microsoft.com/en-us/library/bb356440(v=против 110).aspx

Рейтинг:
1

CPallini

Есть несколько вариантов. Один из методов заключается в следующем:

  • Сначала отсортируйте массив.
  • Затем, foreach item: если он равен следующему, то у вас есть дубликат (и вы можете показать сообщение).


Рейтинг:
1

aarnone2

        static bool hasDuplicates(string s)
        {
            int[] countOfThisCharacter = new int[256];
            bool b = false;
            bool nonunicode = false;

            for (int i=0; i<s.Length; i++)
            {
                if (((int)(s[i]))>255) { nonunicode = true;  break; }
                if ((countOfThisCharacter[s[i]])>0) { b = true; break; }
                countOfThisCharacter[((int)(s[i]))]++;
            }
            if (nonunicode==true)
            {
                b = false;
                Dictionary<string, string> lst = new Dictionary<string, string>();
                for (int i = 0; i < s.Length; i++)
                {
                    if (lst.ContainsKey(s[i].ToString())) { b = true; break; }
                    lst.Add(s[i].ToString(), s[i].ToString());
                }

            }

            return b;
        }

// this is order (N) complexity for strings without Unicode characters
// and order (N log N) complexity for strings that have Unicode characters
//


Dave Kreskowiak

Спрашивали и отвечали больше четырех лет назад.

aarnone2

Да, но этот ответ лучше. Это единственный O(N) способ сделать это.

Dave Kreskowiak

Да, две проблемы.

Во-первых, вы проверяете наличие повторяющихся символов в строке, а не наличие повторяющихся строк в массиве строк. Я допускаю, что первоначальный вопрос оставляет немного места для интерпретации того, о какой ситуации он/она говорил.

Во-вторых, ответ на действительно старый вопрос возвращает его обратно в начало очереди контроля качества. Это то, что нам не нравится, потому что это приводит к большему количеству ответов на действительно старые вопросы, заставляя их появляться в верхней части очереди.

Matt T Heffron

Поскольку ОП говорит "строковый массив", то, по-видимому, нет никакой двусмысленности в постановке задачи. Итак, как вы сказали, это решение не для этой проблемы.

Dave Kreskowiak

Учитывая, что приведенные ответы охватывают оба случая, здесь действительно возникает двусмысленность. Однако большинство ответов охватывают случай string [], а не случай string.chars [].

#realJSOP

Нет, если вы посмотрите на ответ ОП на одно из решений.

Dave Kreskowiak

Единственный ответ, который я увидел, был тот, который сказал: "Никто не работал...", что все еще оставляло вопрос расплывчатым.

Задавать вопросы-это навык, которым ОП, по-видимому, не обладал в то время.

aarnone2

1. не то чтобы это имело значение, но мой подход значительно быстрее для случая string.chars []. Я провел тесты, и это более чем в 5 раз быстрее.

2. я узнал, что такое хэш-набор, и могу использовать его вместо словаря в том случае, когда мне нужно использовать список.

количество повторов: 10000


10.8274
10.0563


количество повторов: 100000


17.0797
97.2567


количество повторов: 1000000


174.4826
959.5027


количество итераций составляет: 10000000


1652.4296
9510.2869


Нажмите любую клавишу, чтобы продолжить ...


использование системы;
использование системы.Коллекции.Общий;
использование System.Linq;
использование System.Text;
использование системы.Нарезание резьбы.Задачи;

пространство имен ConsoleApplication1
{
классная программа
{

статический bool hasDuplicates(строка s)
{
int[] countOfThisCharacter = новый int[256];
bool b = false;
логическое не-Юникод = ложь;

for (int i=0; i<s.Длина; i++)
{
если бы (((тип int)(с[я]))&ГТ;255) { не-Юникод = истина; перерыв; }
if ((countOfThisCharacter[s[i]]) >0) { b = true; break; }
countOfThisCharacter[s[i]]++;
}
if (nonunicode==true)
{
b = ложь;
Для поиска HashSet И Л;строка&ГТ; ЛСТ = новый поиска HashSet И Л;строка&ГТ;();
for (int i = 0; i < s.Length; i++)
{
if (lst.содержит(s[i].ToString())) { b = true; break; }
lst.Add(s[i].Метод toString());
}

}

вернуться б;
}

private static bool HasDuplicates(string s)
{

Для поиска HashSet И Л;строка&ГТ; методы stringset = новый поиска HashSet И Л;строка&ГТ;();
боол hasDups = ложь;
for (int i=0; i<s.Длина; i++)
{
if (stringSet.Contains(s[i].Метод toString()))
{
hasDups = истина;
перерыв;
}
еще
{
методы stringset.Добавить(с[я].Метод toString());
}
}
возвращение hasDups;
}

статический void runTest(int i2)
{
Приставка.WriteLine("количество итераций равно:" + i2.ToString());
Приставка.метод WriteLine("");
Приставка.метод WriteLine("");

bool b;
b = ложь;
DateTime DateTime1 = Система.Датавремя.Сейчас;
for (int i = 0; i < i2; i++)
{
b = hasDuplicates("быстрая бурая лиса перепрыгнула через ленивых собак.");
}
DateTime DateTime2 = Система.Датавремя.Сейчас;
Приставка.WriteLine((DateTime2 - DateTime1).TotalMilliseconds);
b = ложь;

DateTime DateTime3 = Система.Датавремя.Сейчас;
for (int i = 0; i < i2; i++)
{
b = HasDuplicates("быстрая бурая лиса перепрыгнула через ленивых собак.");
}
DateTime DateTime4 = Система.Датавремя.Сейчас;
Приставка.WriteLine((DateTime4 - DateTime3).TotalMilliseconds);




Приставка.метод WriteLine("");
Приставка.метод WriteLine("");

}

static void Main(string[] args)
{

runTest(10000);
runTest(100000);
runTest(1000000);
runTest(10000000);


}
}
}

Рейтинг:
0

#realJSOP

Хотя использование linq - это лучший ответ, вот альтернатива:

string text = "1,2,3,4,4,5";
string[] parts = text.Split(',');
HashSet<string> hset = new Hashset<string>();
foreach(string item in parts)
{
    hset.Add(item);
}
if (hset.Count < parts.Length)
{
   // there's a duplicate string
}


Один HashSet коллекция не допускает дубликатов, но в то же время она не будет выдавать исключение при попытке добавить дубликат.

Если вы хотите знать, какая строка(ы) является/являются дубликатом, вы можете изменить код, чтобы он был примерно таким:
string text = "1,2,3,4,4,5";
string[] parts = text.Split(',');
HashSet<string> hset = new Hashset<string>();
List<string> duplicates = new List<string>
foreach(string item in parts)
{
    int oldCount = hset.Count;
    hset.Add(item);
    if (hset.Count == oldCount)
    {
        if (!duplicates.Contains(item))
        {
            duplicates.Add(item);
        }
    }
}
if (duplicates.Count > 0)
{
   // list the duplicates 
}


Имейте в виду, что приведенный выше код чувствителен к регистру, поэтому "текст" и "текст" будут рассматриваться как разные значения. Если это имеет значение, и если это не будет иметь побочных эффектов в другом месте вашего кода, Вы всегда можете позвонить ToUpper или ToLower на оригинале text varaiable перед обработкой его для дубликатов.

Наконец, пунктуация в предложении может запутать повторяющиеся слова, поэтому вы, вероятно, захотите удалить знаки препинания из исходной строки или удалить их при добавлении в любую из следующих строк. hset и duplicates коллекции (в приведенном выше примере).


Richard MacCutchan

Ох, Джон, проверь дату вопроса.

#realJSOP

Мне все равно. :)

Richard MacCutchan

Бунтарь.

#realJSOP

Чтобы показать, что я готов работать в системе, я опубликовал сообщение suggs/bugs:

https://www.codeproject.com/Messages/5496460/Q-A-Suggestion.aspx

:)

#realJSOP

Я думаю, что вернусь к первому вопросу, когда-либо опубликованному в Q/A, и отвечу на него.

aarnone2

Это решение-O(N log N). Содержится в лог работы Н.

Время, необходимое для создания хэш-таблицы и добавления записей, добавляет сложности. Поиск хэш-таблиц в большинстве случаев близок к O(1), но не совсем O(1)

Хэш, который мы рассматриваем в наиболее распространенном случае, очень мал-он не может быть больше 255 записей для строки, отличной от unicode.

Поэтому я думаю, что мой подход использования массива из 255 целых чисел для всех строк, отличных от unicode, лучше.

#realJSOP

Ваше решение даже не отвечает на вопрос ОП. Основываясь на своих ответах на другие решения, он хотел найти повторяющиеся слова в текстовой строке. Имея это в виду, ваше решение даже не будет работать.

#realJSOP

Итак, вы 1-голосовали за мой ответ, или тот же самый парень, который 1-голосовал за ваш ответ, сделал и мой тоже? Это просто гребаное ребячество.

aarnone2

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