Linq - 将一个 ILookup 转换为另一个 ILookup

发布于 2024-10-01 03:36:28 字数 649 浏览 3 评论 0原文

这应该很简单,但我想不出一个好的方法。如何将一个 ILookup 转换为另一个 ILookup?例如,如何复制/克隆 ILookup,生成具有相同键和相同组的另一个 ILookup?

这是我蹩脚的尝试:

static ILookup<TKey, TValue> Copy<TKey, TValue>(ILookup<TKey, TValue> lookup)
{
    return lookup
        .ToDictionary(
            grouping => grouping.Key,
            grouping => grouping.ToArray())
        .SelectMany(pair =>
            pair
                .Value
                .Select(value =>
                    new KeyValuePair<TKey, TValue>(pair.Key, value)))
        .ToLookup(pair => pair.Key, pair => pair.Value);
}

有人可以改进吗?

——布莱恩

This should be simple, but I can't think of a good way to do it. How do you transform an ILookup into another ILookup? For example, how would you copy/clone an ILookup, producing another ILookup with the same keys and same groups?

Here's my lame attempt:

static ILookup<TKey, TValue> Copy<TKey, TValue>(ILookup<TKey, TValue> lookup)
{
    return lookup
        .ToDictionary(
            grouping => grouping.Key,
            grouping => grouping.ToArray())
        .SelectMany(pair =>
            pair
                .Value
                .Select(value =>
                    new KeyValuePair<TKey, TValue>(pair.Key, value)))
        .ToLookup(pair => pair.Key, pair => pair.Value);
}

Can anyone improve this?

-- Brian

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

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

发布评论

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

评论(2

攒眉千度 2024-10-08 03:36:28

这个怎么样:

return lookup
  .SelectMany (grp => grp, (grp, item) => new { grp.Key, item})
  .ToLookup (x => x.Key, x => x.item);

How about this:

return lookup
  .SelectMany (grp => grp, (grp, item) => new { grp.Key, item})
  .ToLookup (x => x.Key, x => x.item);
一桥轻雨一伞开 2024-10-08 03:36:28

这是你想要的吗?

static ILookup<TKey, TValue> Copy<TKey, TValue>(ILookup<TKey, TValue> lookup)
{
    return lookup.
           SelectMany(g => g,
                     (g, v) => new KeyValuePair<TKey, TValue>(g.Key, v)).
           ToLookup(kvp => kvp.Key, kvp => kvp.Value);
}

当然,如果您想以某种方式转换这些值,也许您想要这样的东西:

static ILookup<TKey, TValueOut> Transform<TKey, TValue, TValueOut>(
       ILookup<TKey, TValue> lookup,
       Func<TValue, TValueOut> selector)
{
    return lookup.
           SelectMany(g => g,
                      (g, v) => new KeyValuePair<TKey, TValueOut>(g.Key, selector(v))).
           ToLookup(kvp => kvp.Key, kvp => kvp.Value);
}

请注意,此方法将中间值保存在 KeyValuePair 中,作为值类型,它存储在堆栈中,因此不需要任何中间内存分配。我分析了一个测试,该测试创建一个包含 100 个键的 Lookup,每个键有 10,000 个项目(总共 1,000,000 个)。

  • 创建 Lookup 进行 1610 次分配。
  • 使用我的方法复制它会进行 1712 次分配(创建它所需的所有分配加上 SelectMany 调用中每个委托的分配以及每个键的枚举器的分配)。
  • 使用匿名对象而不是 KeyValuePair 复制它会进行 1,001,712 次分配(复制所需的所有分配每项加 1)。

从 CPU 角度来看,即使每个键有 100,000 个元素,两种复制方法之间的Lookup性能也是相同的。每个键有 1,000,000 个元素,两种方法的性能有所不同:

  • 创建 5.1 秒,
  • 使用 KeyValuePair 复制 5.9 秒,
  • 使用匿名对象复制 6.3 秒

Does this do what you want?

static ILookup<TKey, TValue> Copy<TKey, TValue>(ILookup<TKey, TValue> lookup)
{
    return lookup.
           SelectMany(g => g,
                     (g, v) => new KeyValuePair<TKey, TValue>(g.Key, v)).
           ToLookup(kvp => kvp.Key, kvp => kvp.Value);
}

Of course, if you want to transform the values somehow, maybe you want something like this:

static ILookup<TKey, TValueOut> Transform<TKey, TValue, TValueOut>(
       ILookup<TKey, TValue> lookup,
       Func<TValue, TValueOut> selector)
{
    return lookup.
           SelectMany(g => g,
                      (g, v) => new KeyValuePair<TKey, TValueOut>(g.Key, selector(v))).
           ToLookup(kvp => kvp.Key, kvp => kvp.Value);
}

Note that this method holds intermediate values in a KeyValuePair which, being a value type, is stored on the stack and thus doesn't require any intermediate memory allocations. I profiled a test that creates a Lookup<int,int> with 100 keys, each having 10,000 items (for a total of 1,000,000).

  • Creating the Lookup does 1610 allocations.
  • Copying it with my method does 1712 allocations (all the allocations required to create it plus one for each delegate in the SelectMany call and one for the enumerator for each key).
  • Copying it with anonymous objects instead of KeyValuePair does 1,001,712 allocations (all the allocations required to copy plus one for each item).

CPU-wise, even with 100,000 elements per key in the Lookup performance between the two copying methods was identical. With 1,000,000 elements per key, the performance was different between the two methods:

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