Каков наиболее эффективный способ сохранить список строк, игнорируя любые дубликаты? Я думал, что словарь может лучше всего вставлять строки, написав dict [str] = false; и перечисление ключей в виде списка. Это хорошее решение?
Каков наиболее эффективный способ сохранить список строк, игнорируя любые дубликаты? Я думал, что словарь может лучше всего вставлять строки, написав dict [str] = false; и перечисление ключей в виде списка. Это хорошее решение?
Ответы:
Если вы используете .NET 3.5, HashSet должен работать на вас.
Класс HashSet <(Of <(T>)>) обеспечивает высокопроизводительные операции над наборами. Набор - это коллекция, которая не содержит повторяющихся элементов и элементы которой не расположены в определенном порядке.
Вы можете сделать что-то вроде этого
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);
Я не уверен, что это можно считать хорошим ответом, но, столкнувшись с необходимостью создания уникального набора, поддерживающего порядок вставки, я пошел на компромисс с HashSet и List рядом. В этом случае всякий раз, когда вы добавляете в набор, сделайте следующее:
if(hashSet.Add(item))
orderList.Add(item);
Удаляя предметы, обязательно снимайте их с обоих. Таким образом, до тех пор, пока вы можете быть уверены, что в список больше ничего не добавлялось, у вас будет уникальный набор, упорядоченный по вставке!
Вы также можете использовать Linq, как в:
using System.Linq;
var items = new List<string>() { "one", "one", "two", "one", "two", "zero" };
List<string> distinctItems = items.Distinct().ToList();
Используйте 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
Это не часть системного пространства имен, но использовались Iesi.Collections из http://www.codeproject.com/KB/recipes/sets.aspx с NHibernate. Он поддерживает хешированный набор вместе с отсортированным набором, набором словарей и т. Д. Поскольку он использовался с NHibernate, он использовался широко и очень стабильно. Это также не требует .Net 3.5
Вот еще одно решение без использования 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
HashSet
потеряет порядок элементов. ФункцияList
предоставляет.