要求:在未排序的列表中,确定是否存在重复项。我这样做的典型方法是n平方嵌套循环。我想知道其他人如何解决这个问题。 Linq有一种优雅,高性能的方法吗?需要lambda或比较器的通用的东西会很好。
答案 0 :(得分:124)
除非我遗漏了某些东西,否则你应该能够使用Distinct()
来解决一些简单的问题。虽然它不会是你能提出的最复杂的实现,但它会告诉你是否删除了任何重复项:
var list = new List<string>();
// Fill the list
if(list.Count != list.Distinct().Count())
{
// Duplicates exist
}
答案 1 :(得分:42)
根据Eric White关于如何Find Duplicates using LINQ:
的文章查找重复项的简单方法是编写按标识符分组的查询,然后筛选具有多个成员的组。在下面的示例中,我们想知道4和3是重复的:
int[] listOfItems = new[] { 4, 2, 3, 1, 6, 4, 3 }; var duplicates = listOfItems .GroupBy(i => i) .Where(g => g.Count() > 1) .Select(g => g.Key); foreach (var d in duplicates) Console.WriteLine(d); // 4,3
答案 2 :(得分:18)
为了在列表的早期存在重复项时允许短路,您可以添加HashSet<T>
并检查其.Add
方法的返回值。
通过使用.Any
,您可以在找到副本时立即将枚举短路。
这是C#和VB中的LINQ扩展方法:
public static bool ContainsDuplicates<T>(this IEnumerable<T> enumerable)
{
var knownKeys = new HashSet<T>();
return enumerable.Any(item => !knownKeys.Add(item));
}
<Extension>
Public Function ContainsDuplicates(Of T)(ByVal enumerable As IEnumerable(Of T)) As Boolean
Dim knownKeys As New HashSet(Of T)
Return enumerable.Any(Function(item) Not knownKeys.Add(item))
End Function
注意:要检查是否有没有重复项,只需将Any
更改为All
答案 3 :(得分:13)
将所有项目放在一个集合中,如果该集合的计数与列表的计数不同,则会有重复。
bool hasDuplicates<T>(List<T> myList) {
var hs = new HashSet<T>();
for (var i = 0; i < myList.Count; ++i) {
if (!hs.Add(myList[i])) return true;
}
return false;
}
应该比Distinct更有效,因为不需要遍历所有列表。
答案 4 :(得分:2)
沿着这些方向的东西相对简单,并且会为您提供重复的计数。
var something = new List<string>() { "One", "One", "Two", "Three" };
var dictionary = new Dictionary<string, int>();
something.ForEach(s =>
{
if (dictionary.ContainsKey(s))
{
dictionary[s]++;
}
else
{
dictionary[s] = 1;
}
});
我想这与Distinct的实现相似,虽然我不确定。
答案 5 :(得分:2)
您可以使用IEnumerable.GroupBy方法。
var list = new List<string> {"1", "2","3", "1", "2"};
var hasDuplicates = list.GroupBy(x => x).Any(x => x.Skip(1).Any());
答案 6 :(得分:1)
您可以对IEnumerable使用Distinct()扩展方法
答案 7 :(得分:1)
如果使用整数或排序良好的集合,请使用二叉树表示O(nlog n)性能。
或者,找到另一种更快的排序方法,然后只需检查每个值是否与前一个值不同。
答案 8 :(得分:1)
将Enumerable.Any
与HashSet.Add
一起使用,如:
List<string> list = new List<string> {"A", "A", "B", "C", "D"};
HashSet<string> hashSet = new HashSet<string>();
if(list.Any(r => !hashSet.Add(r)))
{
//duplicate exists.
}
如果该项目已存在于HashSet.Add
中,则 false
将返回HashSet
。这不会迭代整个列表。
答案 9 :(得分:0)
您可以使用Distinct()
语句查找唯一记录。然后与原始通用列表进行比较:
if (dgCoil.ItemsSource.Cast<BLL.Coil>().ToList().Count != dgCoil.ItemsSource.Cast<BLL.Coil>().Select(c => c.CoilNo).Distinct().Count())
{
//Duplicate detected !!
return;
}
答案 10 :(得分:-1)
还没有看到有人这样做,所以这里是我刚写的一个小程序。这很简单。使用Contains(),虽然我不知道这种方法的可扩展性如何。
Console.WriteLine("Please enter 5 unique numbers....");
List<int> uniqueNums = new List<int>() { };
while (uniqueNums.Count < 5)
{
int input = Convert.ToInt32(Console.ReadLine());
if (uniqueNums.Contains(input))
{
Console.WriteLine("Add a different number");
}
uniqueNums.Add(input);
}
uniqueNums.Sort();
foreach (var n in uniqueNums)
{
Console.WriteLine(n);
}