我讨厌发布它,因为它有些主观,但是感觉有一种更好的方法,我只是没有想到。

有时,我想通过某些列/属性“区分”集合,但又不丢弃其他列(是的,这的确会丢失信息,因为它会随心所欲地变成其他列的哪个值)。

请注意,此扩展功能不如采用IEqualityComparer<T>的Distinct重载强大,因为此类操作可以执行更复杂的比较逻辑,但这只是我现在所需要的:)

public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> getKeyFunc)
{
    return from s in source
            group s by getKeyFunc(s) into sourceGroups
            select sourceGroups.First();
}


用法示例:

var items = new[]
{
    new { A = 1, B = "foo", C = Guid.NewGuid(), },
    new { A = 2, B = "foo", C = Guid.NewGuid(), },
    new { A = 1, B = "bar", C = Guid.NewGuid(), },
    new { A = 2, B = "bar", C = Guid.NewGuid(), },
};

var itemsByA = items.DistinctBy(item => item.A).ToList();
var itemsByB = items.DistinctBy(item => item.B).ToList();

最佳答案

干得好。我不认为这比您自己的版本要有效得多,但是应该有一点优势。它只需要对序列进行一次遍历,就可以对每一项进行yield处理,而无需首先对整个序列进行分组。

public static IEnumerable<TSource> DistinctBy<TSource, TKey>(
    this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
    return source.DistinctBy(keySelector, null);
}

public static IEnumerable<TSource> DistinctBy<TSource, TKey>(
    this IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector, IEqualityComparer<TKey> keyComparer)
{
    if (source == null)
        throw new ArgumentNullException("source");

    if (keySelector == null)
        throw new ArgumentNullException("keySelector");

    return source.DistinctByIterator(keySelector, keyComparer);
}

private static IEnumerable<TSource> DistinctByIterator<TSource, TKey>(
    this IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector, IEqualityComparer<TKey> keyComparer)
{
    var keys = new HashSet<TKey>(keyComparer);

    foreach (TSource item in source)
    {
        if (keys.Add(keySelector(item)))
            yield return item;
    }
}

关于c# - “更好的”(更简单,更快,什么)版本的“与众不同”?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3259816/

10-11 04:34