Дубликат IEnumerable, список и приведение - PullRequest
1 голос
/ 18 октября 2011

после прочтения этой очень интересной темы об удалении дубликатов , я закончил этим =>

    public static IEnumerable<T> deDuplicateCollection<T>(IEnumerable<T> input)
    {
        var hs = new HashSet<T>();
        foreach (T t in input)
            if (hs.Add(t))
                yield return t;
    }        

кстати, поскольку я новичок в C # и пришел из Python, я немного растерялся между кастами и подобными вещами ... я смог собрать и собрать с помощью:

            foreach (KeyValuePair<long, List<string>> kvp in d)
            {
                d[kvp.Key] = (List<string>) deDuplicateCollection(kvp.Value);
            }

но я, должно быть, что-то здесь упустил ... так как я получаю "System.InvalidCastException" @ runtime, может, не могли бы вы указать интересные вещи о приведении и в чем я не прав? Заранее спасибо.

Ответы [ 2 ]

3 голосов
/ 18 октября 2011

Во-первых, об использовании метода.

Бросить приведение, вызвать ToList() в результате метода.Результат метода IEnumerable<string>, это не List<string>.Тот факт, что источник изначально a List<string> не имеет значения, вы не возвращаете список, вы yield return последовательность.

d[kvp.Key] = deDuplicateCollection(kvp.Value).ToList();

Во-вторых, ваш deDuplicateCollection методявляется избыточным, Distinct() уже существует в библиотеке и выполняет ту же функцию.

d[kvp.Key] = kvp.Value.Distinct().ToList();

Просто убедитесь, что у вас есть using System.Linq; в директивах, чтобы вы могли использовать эти Distinct() и ToList()методы расширения.

Наконец, вы заметите, что, сделав это изменение в одиночку , вы столкнетесь с новым исключением при попытке изменить словарь в цикле.Вы не можете обновить коллекцию в foreach.Самый простой способ сделать то, что вы хотите, это полностью пропустить явный цикл.Рассмотрим

d = d.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.Distinct().ToList());

При этом используется другой метод расширения Linq, ToDictionary().Примечание: это создает новый словарь в памяти и обновляет d для ссылки на него.Если вам нужно сохранить исходный словарь, на который ссылается d, то вам нужно подойти к этому по-другому.Простым вариантом здесь является создание словаря для тени d, а затем обновление d с ним.

var shadow = new Dictionary<string, string>();
foreach (var kvp in d)
{ 
    shadow[kvp.Key] = kvp.Value.Distinct().ToList();
}

foreach (var kvp in shadow)
{
    d[kvp.Key] = kvp.Value;
}

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

2 голосов
/ 18 октября 2011
d[kvp.Key] = kvp.Value.Distinct().ToList();

Уже существует Distinct метод расширения для удаления дубликатов!

...