我有一个集合:
List<Car> cars = new List<Car>();
汽车通过它们的属性CarCode
进行唯一标识。
我有三辆汽车在集合中,其中两辆具有相同的CarCode。
如何使用LINQ将此集合转换为具有唯一CarCodes的汽车?
List<Car> distinct =
cars
.GroupBy(car => car.CarCode)
.Select(g => g.First())
.ToList();
First()
完全没有问题。 - Maximilian AstDistinctBy
方法(https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.distinctby?view=net-6.0)。 - peflorencio使用MoreLINQ,该库中有一个名为DistinctBy
的方法 :)
IEnumerable<Car> distinctCars = cars.DistinctBy(car => car.CarCode);
(仅适用于LINQ to Objects。)
NO_HASHSET
为真,则是您的版本...)吗?非常感谢! - gdoronIQueryable<T>
一起使用,并尝试对其进行DistinctBy
,从而查询整个该死的表格...这不是容易出错吗?再次感谢您非常快速的回复! - gdoronSystem
下的代码有点紧张,因为这给人一种它是“官方”的错误印象。当然,你的品味可能有所不同 :) - Jon Skeet与Guffa的方法相同,但作为扩展方法:
public static IEnumerable<T> DistinctBy<T, TKey>(this IEnumerable<T> items, Func<T, TKey> property)
{
return items.GroupBy(property).Select(x => x.First());
}
用作:
var uniqueCars = cars.DistinctBy(x => x.CarCode);
你可以实现一个IEqualityComparer,并在Distinct扩展方法中使用它。
class CarEqualityComparer : IEqualityComparer<Car>
{
#region IEqualityComparer<Car> Members
public bool Equals(Car x, Car y)
{
return x.CarCode.Equals(y.CarCode);
}
public int GetHashCode(Car obj)
{
return obj.CarCode.GetHashCode();
}
#endregion
}
然后
var uniqueCars = cars.Distinct(new CarEqualityComparer());
cars.Distinct(new GenericEqualityComparer<Car>((a,b) => a.CarCode == b.CarCode, x => x.CarCode.GetHashCode()))
。我过去曾经使用过这样的方法,因为在执行一次性Distinct时,它有时会增加价值。 - user2864740另一种用于Linq-to-Objects的扩展方法,不使用GroupBy:
/// <summary>
/// Returns the set of items, made distinct by the selected value.
/// </summary>
/// <typeparam name="TSource">The type of the source.</typeparam>
/// <typeparam name="TResult">The type of the result.</typeparam>
/// <param name="source">The source collection.</param>
/// <param name="selector">A function that selects a value to determine unique results.</param>
/// <returns>IEnumerable<TSource>.</returns>
public static IEnumerable<TSource> Distinct<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector)
{
HashSet<TResult> set = new HashSet<TResult>();
foreach(var item in source)
{
var selectedValue = selector(item);
if (set.Add(selectedValue))
yield return item;
}
}
var filtered = taskList.DistinctBy(t => t.TaskExternalId).ToArray();
扩展方法代码
public static class LinqExtensions
{
public static IEnumerable<T> DistinctBy<T, TKey>(this IEnumerable<T> items, Func<T, TKey> property)
{
GeneralPropertyComparer<T, TKey> comparer = new GeneralPropertyComparer<T,TKey>(property);
return items.Distinct(comparer);
}
}
public class GeneralPropertyComparer<T,TKey> : IEqualityComparer<T>
{
private Func<T, TKey> expr { get; set; }
public GeneralPropertyComparer (Func<T, TKey> expr)
{
this.expr = expr;
}
public bool Equals(T left, T right)
{
var leftProp = expr.Invoke(left);
var rightProp = expr.Invoke(right);
if (leftProp == null && rightProp == null)
return true;
else if (leftProp == null ^ rightProp == null)
return false;
else
return leftProp.Equals(rightProp);
}
public int GetHashCode(T obj)
{
var prop = expr.Invoke(obj);
return (prop==null)? 0:prop.GetHashCode();
}
}
完成相同任务的另一种方法...
List<Car> distinticBy = cars
.Select(car => car.CarCode)
.Distinct()
.Select(code => cars.First(car => car.CarCode == code))
.ToList();
可以创建一个扩展方法以更通用的方式实现此操作。如果有人能够评估这个“DistinctBy”与“GroupBy”方法的性能,那将是很有趣的。
Select
将是一个 O(n*m) 操作,因此它不会很好地扩展。如果有很多重复项,即如果第一个 Select
的结果是原始集合的非常小的一部分,则它可能会表现得更好。 - Guffausing PowerfulExtensions.Linq;
...
var distinct = myArray.Distinct(x => x.A, x => x.B);
myList.Distinct(x => x.ID)
? - Thomas