使用LINQ,从一个列表<int>,我怎么能检索一个列表,包含重复不止一次的条目和他们的值?
当前回答
按键删除重复项
myTupleList = myTupleList.GroupBy(tuple => tuple.Item1).Select(group => group.First()).ToList();
其他回答
解决这个问题最简单的方法是根据元素的值对它们进行分组,然后如果组中有多个元素,则选择组中的一个代表。在LINQ中,这转换为:
var query = lst.GroupBy(x => x)
.Where(g => g.Count() > 1)
.Select(y => y.Key)
.ToList();
如果你想知道元素重复了多少次,你可以使用:
var query = lst.GroupBy(x => x)
.Where(g => g.Count() > 1)
.Select(y => new { Element = y.Key, Counter = y.Count() })
.ToList();
这将返回一个匿名类型的List,每个元素将具有element和Counter属性,以检索所需的信息。
最后,如果你要找的是字典,你可以用
var query = lst.GroupBy(x => x)
.Where(g => g.Count() > 1)
.ToDictionary(x => x.Key, y => y.Count());
这将返回一个字典,以您的元素为键,并将其重复的次数作为值。
你可以这样做:
var list = new[] {1,2,3,1,4,2};
var duplicateItems = list.Duplicates();
使用这些扩展方法:
public static class Extensions
{
public static IEnumerable<TSource> Duplicates<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector)
{
var grouped = source.GroupBy(selector);
var moreThan1 = grouped.Where(i => i.IsMultiple());
return moreThan1.SelectMany(i => i);
}
public static IEnumerable<TSource> Duplicates<TSource, TKey>(this IEnumerable<TSource> source)
{
return source.Duplicates(i => i);
}
public static bool IsMultiple<T>(this IEnumerable<T> source)
{
var enumerator = source.GetEnumerator();
return enumerator.MoveNext() && enumerator.MoveNext();
}
}
在duplicate方法中使用IsMultiple()比Count()更快,因为这不会迭代整个集合。
所有的GroupBy答案都是最简单的,但不是最有效的。它们对内存性能尤其不利,因为构建大型内部集合需要分配成本。
一个不错的替代方案是HuBeZa的HashSet。基于添加的方法。它表现得更好。
如果你不关心空值,就我所知,像这样的东西是最有效的(CPU和内存):
public static IEnumerable<TProperty> Duplicates<TSource, TProperty>(
this IEnumerable<TSource> source,
Func<TSource, TProperty> duplicateSelector,
IEqualityComparer<TProperty> comparer = null)
{
comparer ??= EqualityComparer<TProperty>.Default;
Dictionary<TProperty, int> counts = new Dictionary<TProperty, int>(comparer);
foreach (var item in source)
{
TProperty property = duplicateSelector(item);
counts.TryGetValue(property, out int count);
switch (count)
{
case 0:
counts[property] = ++count;
break;
case 1:
counts[property] = ++count;
yield return property;
break;
}
}
}
这里的技巧是在重复数达到1时避免额外的查找成本。当然,如果您还想知道每个项重复出现的次数,则可以使用count不断更新字典。对于null,你只需要一些额外的处理,仅此而已。
这种更简单的方法,不使用组,只是获得区域元素,然后迭代它们,并检查它们在列表中的计数,如果它们的计数是>1,这意味着它出现超过1项,所以将其添加到Repeteditemlist
var mylist = new List<int>() { 1, 1, 2, 3, 3, 3, 4, 4, 4 };
var distList= mylist.Distinct().ToList();
var Repeteditemlist = new List<int>();
foreach (var item in distList)
{
if(mylist.Count(e => e == item) > 1)
{
Repeteditemlist.Add(item);
}
}
foreach (var item in Repeteditemlist)
{
Console.WriteLine(item);
}
预期的输出:
1 3 4
完整的集Linq到SQL扩展的重复功能检查在MS SQL Server。不使用. tolist()或IEnumerable。这些查询在SQL Server中执行,而不是在内存中。结果只在内存中返回。
public static class Linq2SqlExtensions {
public class CountOfT<T> {
public T Key { get; set; }
public int Count { get; set; }
}
public static IQueryable<TKey> Duplicates<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> groupBy)
=> source.GroupBy(groupBy).Where(w => w.Count() > 1).Select(s => s.Key);
public static IQueryable<TSource> GetDuplicates<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> groupBy)
=> source.GroupBy(groupBy).Where(w => w.Count() > 1).SelectMany(s => s);
public static IQueryable<CountOfT<TKey>> DuplicatesCounts<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> groupBy)
=> source.GroupBy(groupBy).Where(w => w.Count() > 1).Select(y => new CountOfT<TKey> { Key = y.Key, Count = y.Count() });
public static IQueryable<Tuple<TKey, int>> DuplicatesCountsAsTuble<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> groupBy)
=> source.GroupBy(groupBy).Where(w => w.Count() > 1).Select(s => Tuple.Create(s.Key, s.Count()));
}