LINQ To 对象 GroupBy 方法

发布于 2024-11-08 22:13:28 字数 78 浏览 0 评论 0原文

LINQ To Objects GroupBy 方法如何工作?它是否会遍历整个集合中的每个键?有没有办法告诉 GroupBy 方法集合已排序?

How does LINQ To Objects GroupBy method work? Does it look throught the whole collection for each key? Is there any way to say to GroupBy method that collection is sorted?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

等你爱我 2024-11-15 22:13:28

如果做得明智,GroupBy 将在单次向前传递中发挥作用。基本的实现(不是他们的)类似于:

var data = new Dictionary<TKey, List<TValue>>(comparer);
foreach(var item in source) {
    var key = keySelector(item);
    List<TValue> list;
    if(!data.TryGetValue(key, out list))
    {
        data.Add(key, list = new List<TValue>());
    }
    list.Add(itemSelector(item));
}

基本上按键分组,为每个唯一键创建一个包含值的列表。

可以做一些事情,例如与最后看到的键进行比较(以帮助排序数据),但是......您需要进行分析才能知道它是否值得。

GroupBy, if done sensibly, would work in a single forwards only pass. A basic implementation (not theirs) would be something comparable to:

var data = new Dictionary<TKey, List<TValue>>(comparer);
foreach(var item in source) {
    var key = keySelector(item);
    List<TValue> list;
    if(!data.TryGetValue(key, out list))
    {
        data.Add(key, list = new List<TValue>());
    }
    list.Add(itemSelector(item));
}

That basically groups by key, creating a list for each unique key, containing the values.

You could do things like compare to the last-seen key (to help with sorted data), but... you'd need to profile to know if it is worthwhile.

梦冥 2024-11-15 22:13:28

让我们看看重载

IEnumerable<IGrouping<TKey, TSource>> Enumerable.GroupBy<TSource, TKey>(
    this IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector
);

,因为它是最容易理解的。实际上,代码将执行如下操作:

枚举 source

对于源中的每个 element,将元素映射到 key = keySelector(element)

看看是否key 位于由 TKey 键控的字典中
如果不是,请添加值为 Listkey 和第一项 element
否则,获取与键关联的 List 并将 element 添加到列表中

现在您有一个字典映射 TKey -> TSource并且可以轻松产生IGrouping序列。

因此,像

var dictionary = new Dictionary<TKey, List<TSource>> dictionary;
foreach(var element in source) {
    key = keySelector(element);
    List<TSource> list;
    if(!dictionary.TryGetValue(key, out list)) {
        list = new List<TSource>();
        dictionary.Add(key, list);
    }
    list.Add(element);
}

从这里开始,您可以轻松生成 IGrouping 序列。

我不明白为什么你认为排序列表很重要。

Let's just look at the overload

IEnumerable<IGrouping<TKey, TSource>> Enumerable.GroupBy<TSource, TKey>(
    this IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector
);

as its the simplest to understand. Effectively the code will do something like this:

Enumerate through source

For each element in source, map element to key = keySelector(element)

See if key is in a dictionary keyed by TKey
if it is not, add the key with the value a List<TSource> and first item element
else, get the List<TSource> associated to key and add element to the list

Now you have a dictionary mapping TKey -> TSource and can easily produce a sequence of IGrouping<TKey, TElement>.

So something like

var dictionary = new Dictionary<TKey, List<TSource>> dictionary;
foreach(var element in source) {
    key = keySelector(element);
    List<TSource> list;
    if(!dictionary.TryGetValue(key, out list)) {
        list = new List<TSource>();
        dictionary.Add(key, list);
    }
    list.Add(element);
}

From here you can easily yield a sequence of IGrouping<TKey, TSource>.

I don't see why you think the list being sorted matters.

九厘米的零° 2024-11-15 22:13:28

它是否会遍历整个集合中的每个键?

不会。GroupBy 的实现是 O(n),而不是 O(n^2)

Does it look throught the whole collection for each key?

No. The implementation of GroupBy is O(n), not O(n^2)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文