首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么没有Linq方法通过谓词返回不同的值?

为什么没有Linq方法通过谓词返回不同的值?
EN

Stack Overflow用户
提问于 2009-02-06 11:51:53
回答 3查看 14.9K关注 0票数 51

我想要在列表中获得不同的值,而不是通过标准的相等比较。

我想做的是这样的:

return myList.Distinct( (x, y) => x.Url == y.Url );

我不能,Linq中没有可以做到这一点的扩展方法--只有一个接受IEqualityComparer的方法。

我可以用这个来解决这个问题:

return myList.GroupBy( x => x.Url ).Select( g => g.First() );

但这看起来很混乱。它也不能做同样的事情-我只能在这里使用它,因为我有一个单一的密钥。

我也可以添加我自己的:

public static IEnumerable<T> Distinct<T>( 
    this IEnumerable<T> input, Func<T,T,bool> compare )
{
    //write my own here
}

但这看起来确实更像是写了一些一开始就应该存在的东西。

有人知道为什么这里没有这种方法吗?

我是不是遗漏了什么?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2009-02-06 12:00:35

当然,这很烦人。这也是我的"MoreLINQ“项目的一部分,在某种程度上我必须加以注意:)在对投影进行操作时,还有许多其他操作是有意义的,但将原始的- MaxBy和MinBy spring返回到脑海中。

正如你所说,它很容易写-尽管我更喜欢名字"DistinctBy“来匹配OrderBy等。如果你感兴趣,这里是我的实现:

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

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

    private static IEnumerable<TSource> DistinctByImpl<TSource, TKey>
        (IEnumerable<TSource> source,
         Func<TSource, TKey> keySelector,
         IEqualityComparer<TKey> comparer)
    {
        HashSet<TKey> knownKeys = new HashSet<TKey>(comparer);
        foreach (TSource element in source)
        {
            if (knownKeys.Add(keySelector(element)))
            {
                yield return element;
            }
        }
    }
票数 58
EN

Stack Overflow用户

发布于 2010-10-09 02:29:27

乔恩,你的解决方案很不错。不过,有一个小小的变化。我不认为我们需要EqualityComparer.Default在那里。这是我的解决方案(当然,起点是Jon Skeet的解决方案)

    public static IEnumerable<T> DistinctBy<T, TKey>(this IEnumerable<T> source, Func<T, TKey> keySelector)
    {
        //TODO All arg checks
        HashSet<TKey> keys = new HashSet<TKey>();
        foreach (T item in source)
        {
            TKey key = keySelector(item);
            if (!keys.Contains(key))
            {
                keys.Add(key);
                yield return item;
            }
        }
    }
票数 3
EN

Stack Overflow用户

发布于 2016-09-01 16:02:14

使用AmyB的answer,我编写了一个小的DistinctBy扩展方法,以允许传递谓词:

/// <summary>
/// Distinct method that accepts a perdicate
/// </summary>
/// <typeparam name="TSource">The type of the t source.</typeparam>
/// <typeparam name="TKey">The type of the t key.</typeparam>
/// <param name="source">The source.</param>
/// <param name="predicate">The predicate.</param>
/// <returns>IEnumerable&lt;TSource&gt;.</returns>
/// <exception cref="System.ArgumentNullException">source</exception>
public static IEnumerable<TSource> DistinctBy<TSource, TKey>
    (this IEnumerable<TSource> source,
     Func<TSource, TKey> predicate)
{
    if (source == null)
        throw new ArgumentNullException("source");

    return source
        .GroupBy(predicate)
        .Select(x => x.First());
}

现在,您可以传递一个谓词来对列表进行分组:

var distinct = myList.DistinctBy(x => x.Id);

或按多个属性分组:

var distinct = myList.DistinctBy(x => new { x.Id, x.Title });
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/520030

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档