阅读此very interesting thread on duplicate removal后,我结束了这个=>
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”@运行时,也许你能指出有关铸造的有趣事情以及我错在哪里?提前谢谢。
答案 0 :(得分:3)
首先,关于该方法的用法。
删除演员表,在方法的结果上调用ToList()
。该方法的结果是IEnumerable<string>
,这不是List<string>
。源最初 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;
}
这两个循环是安全的,但是你看到你需要循环两次以避免在枚举时更新原始集合的问题,同时还保留了内存中的原始集合。
答案 1 :(得分:2)
d[kvp.Key] = kvp.Value.Distinct().ToList();
已经有一个Distinct
扩展方法可以删除重复项!