Ефективний перелік унікальних рядків C #


86

Який найефективніший спосіб зберігати список рядків, ігноруючи дублікати? Я думав, що словник може найкраще вставити рядки, написавши dict [str] = false; і перерахування за допомогою клавіш у вигляді списку. Це хороше рішення?

Відповіді:


111

Якщо ви використовуєте .NET 3.5, HashSet повинен працювати для вас.

Клас HashSet <(Of <(T>)>) забезпечує високу продуктивність набору операцій. Набір - це колекція, яка не містить повторюваних елементів і елементи якої не в певному порядку.


5
Але а HashSetвтратить порядок предметів. Функція a Listнадає.
— aggsol

4
Додатково: Існує також SortedSet <T>, який є зручним відсортованим HashSet.
— WhoIsRich

Також зверніть увагу, що доступ до HashSet неможливий за допомогою індексу, лише через перерахувальник, на відміну від списку.
— Ендрю

23

Ви можете подивитися, щоб зробити щось подібне

var hash = new HashSet<string>();
var collectionWithDup = new []{"one","one","two","one","two","zero"}; 

// No need to check for duplicates as the Add method
// will only add it if it doesn't exist already
foreach (var str in collectionWithDup)
    hash.Add(str);   

33
Вам не потрібна перевірка Contains за допомогою HashSet. Ви можете просто викликати метод Add, і він поверне true або false залежно від того, чи вже існує елемент.
— LukeH

1
Відповідь слід відредагувати, щоб видалити дзвінок надлишковим Contains. Це все, що потрібно для роботи наведеного вище прикладу: var collectionWithDup = new [] {"one", "one", "two", "one", "two", "zero"}; var uniqueValues ​​= новий HashSet <string> (collectionWithDup);
— user3285954

14

Я не впевнений, що це вважається гарною відповіддю, але, зіткнувшись з необхідністю унікального набору, який підтримує порядок вставки, я пішов на компроміс із HashSet і List поруч. У цьому випадку кожного разу, коли ви додаєте до набору, виконайте такі дії:

if(hashSet.Add(item))
    orderList.Add(item);

Виймаючи предмети, обов’язково виймайте їх з обох. Таким чином, поки ви можете бути впевнені, що ніщо інше не додало елементи до списку, ви будете мати унікальний набір, замовлений вставкою!


10

Ви також можете використовувати Linq як у:

using System.Linq;

var items = new List<string>() { "one", "one", "two", "one", "two", "zero" };

List<string> distinctItems = items.Distinct().ToList();

8

Використовуйте HashSet, не потрібно перевіряти .Contains (), просто додайте свої елементи до списку, і якщо його дублікат він не додасть.

   HashSet<int> uniqueList = new HashSet<int>();
   uniqueList.Add(1); // List has values 1
   uniqueList.Add(2);  // List has values 1,2
   uniqueList.Add(1);  // List has values 1,2
   Console.WriteLine(uniqueList.Count); // it will return 2

2

Це не є частиною системного простору імен, але використовували колекції Iesi.Collections з http://www.codeproject.com/KB/recipes/sets.aspx із NHibernate. Він підтримує хешований набір разом із відсортованим набором, набором словників тощо. Оскільки його застосовували з NHibernate, він використовувався широко і дуже стабільно. Це також не вимагає .Net 3.5


2

Ось ще одне рішення без використання HashSet.

var items = new List<string>() { "one", "one", "two", "one", "two", "zero" };
var uniqueItems = items.Where((item, index) => items.IndexOf(item) == index);

Це було прийнято з цього потоку: javascript - унікальні значення в масиві

Тест:

using FluentAssertions;

uniqueItems.Count().Should().Be(3);
uniqueItems.Should().BeEquivalentTo("one", "two", "zero");

Тест продуктивності для List, HashSetі SortedSet. 1 мільйон ітерацій:

List: 564 ms
HashSet: 487 ms
SortedSet: 1932 ms

Перевірте вихідний код (суть)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.