C#确定列表中的重复项

kak*_*dge 61 c# linq generics algorithm list

要求:在未排序的列表中,确定是否存在重复项.我这样做的典型方法是n平方嵌套循环.我想知道其他人如何解决这个问题.Linq有一种优雅,高性能的方法吗?需要lambda或比较器的通用的东西会很好.

Jus*_*ner 131

除非我遗漏了某些东西,否则你应该能够使用简单的东西Distinct().虽然它不会是你能提出的最复杂的实现,但它会告诉你是否删除了任何重复项:

var list = new List<string>();

// Fill the list

if(list.Count != list.Distinct().Count())
{
     // Duplicates exist
}
Run Code Online (Sandbox Code Playgroud)

  • + 1,如果我没记错的话`Distinct()`在内部使用Hashtable,所以应该是O(n) (6认同)
  • 当您访问列表 3 次时,此解决方案似乎并不快。我会考虑向 HasSet 添加元素,直到它返回 false。 (3认同)
  • 不要调用list.Count()方法.请改用Count属性.我知道LINQ已经过优化,它将在内部使用它,但我认为最好使用该属性. (2认同)

Ali*_*Ali 44

根据Eric White关于如何使用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
Run Code Online (Sandbox Code Playgroud)

  • 如果您需要知道重复值,这会更有帮助. (9认同)
  • 这肯定会有效但需要的时间比必要的时间长(OP只需要知道是否存在重复...不是重复值是什么). (4认同)

Kyl*_*Mit 20

如果在列表的早期存在重复项时允许短路,则可以添加HashSet<T>并检查其.Add方法的返回值.

通过使用,.Any您可以在发现重复时立即短路枚举.

这是C#和VB中的LINQ扩展方法:

CSHARP:

public static bool ContainsDuplicates<T>(this IEnumerable<T> enumerable)
{
    var knownKeys = new HashSet<T>();
    return enumerable.Any(item => !knownKeys.Add(item));
}
Run Code Online (Sandbox Code Playgroud)

Visual Basic:

<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
Run Code Online (Sandbox Code Playgroud)

注意:要检查是否没有重复项,只需更改AnyAll

  • 这很好,很优雅,类似于 [此处描述](http://stackoverflow.com/a/19476092/24874) 的方法,它也返回重复项。 (2认同)
  • @MihaiSocaciu,因为这种短路,意味着一旦满足标准,它就不必检查可能非常大的集合中的每个元素 (2认同)

Tri*_*dad 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;
}
Run Code Online (Sandbox Code Playgroud)

应该比Distinct更有效,因为不需要遍历所有列表.

  • 不要调用list.Count()方法.请改用Count属性.我知道LINQ已经过优化,它将在内部使用它,但我认为最好使用该属性. (5认同)
  • 如果有重复*,则会更高效*.但如果没有重复,那么它的工作量相同.使用哪一个可能取决于"正常"情况是否没有重复. (3认同)

小智 8

您可以使用 IEnumerable.GroupBy 方法。

var list = new List<string> {"1", "2","3", "1", "2"};
var hasDuplicates = list.GroupBy(x => x).Any(x => x.Skip(1).Any());
Run Code Online (Sandbox Code Playgroud)