【问题标题】:C# - combining collections questionC# - 组合集合问题
【发布时间】:2011-03-27 21:46:26
【问题描述】:

如果我有IDictionary<int, int>,是否有可能收到IEnumerable<int>,它 将包含每个 KeyValuePair<int, int> 反汇编成两个 (int, int) 条目一个接一个插入?

小例子:

Dictionary:
5 - 25
6 - 36
7 - 49

Wanted Enumerable:
5, 25, 6, 36, 7, 49

另外,我想在一个超级漂亮的声明中包含这个,但我想不出一个合适的:)


更新:

LINQ 是否允许在每个 .Select 语句中插入多个元素,共享以下思想:

xyz.Select(t => (t, null))

所以生成的Enumerable 将在其后包含tnull

【问题讨论】:

  • 无论您选择哪种解决方案,请记住,字典不能保证枚举的顺序。因此,在您的示例中,您可以得到 "6, 36, 5, 25, 7, 49" 。如果你确实想要一些订单,你可以使用 OrderBy。

标签: c# linq collections merge


【解决方案1】:

您可以使用SelectMany<TSource, TResult>(IEnumerable<TSource>, Func<TSource, IEnumerable<TResult>>)(加上重载)。这是一个例子

var dict = new Dictionary<int, int> {
   { 5, 25 },
   { 6, 36 },
   { 7, 49 } 
}; 

var projection = dict.SelectMany(kv => new[] { kv.Key, kv.Value });

根据 cmets,这只是实现您所要求的一种方式。

【讨论】:

  • 不是真的,你可以(ab)使用dict.SelectMany(kvp =&gt; new [] { kvp.Key, kvp.Value }),前提是可以为键和值类型推断枚举类型
  • SelectMany 可能不是理想的用例,但相对干净且易于理解,前提是可以推断出枚举类型。
  • +1:这看起来有点老套,但这是我会做的,当然这是完成内置方法所要求的唯一方法。
  • 考虑一下,即使无法推断类型,您也必须将类型强制转换为委托/lambda 中的“通用类型分母”,这是您必须做的据我所知,无论如何都要使用一个迭代器块枚举所有键和值。
【解决方案2】:

您可以创建一个方法,以您想要的方式将您的字典分解为 IEnumerable。

using System.Collections.Generic;
using System;

public class C {

    public static void Main()
    {
        var dic = new Dictionary<int,int>();
        dic[0] = 1;
        dic[2] = 3;
        dic[4] = 5;

        foreach (var i in Decompose(dic))
            Console.WriteLine(i);

        Console.ReadLine();
    }

    public static IEnumerable<int> Decompose(IDictionary<int,int> dic)
    {
        foreach (var i in dic.Keys)
        {
            yield return i;
            yield return dic[i];
        }
    }
}

输出:

  0
  1
  2
  3
  4
  5

【讨论】:

  • +1 因为有一个简单的解决方案,该解决方案可以按要求完成,而不是类似的(或在某些情况下甚至不接近)。
【解决方案3】:

我认为这是

var enumerable = Mix(dict.Keys, dict.Values);

我相信 .NET framework 4.0 Enumerable.Zip 会接近[1]

所以我找到了时间来实现这个MixSequences 方法,请注意我是如何将它做成 n 元的,所以它可以组合任意数量的序列(不仅仅是 2 个) .

using System;
using System.Linq;
using System.Collections.Generic;

namespace NS
{
    static class Program
    {
        private static IEnumerable<T> MixSequences<T> (params IEnumerable<T>[] sequences)
        {
            var se = sequences.Select(s => s.GetEnumerator()).ToList();
            try
            {
                while (se.All(e => e.MoveNext()))
                    foreach (var v in se.Select(e => e.Current))
                        yield return v;
            }
            finally
            { se.ForEach(e => e.Dispose()); }
        }

        public static void Main(string[] args)
        {
            var dict = new Dictionary<int,int>{ {1,4},{13,8},{2,1} };
            var twin = new Dictionary<int,int>{ {71,74},{83,78},{72,71} };

            Console.WriteLine("Keys: {0}", string.Join(", ", dict.Keys));
            Console.WriteLine("Values: {0}", string.Join(", ", dict.Values));
            Console.WriteLine("Proof of pudding: {0}", string.Join(", ", MixSequences(dict.Keys, dict.Values)));
            Console.WriteLine("For extra super fun: {0}", string.Join(", ", MixSequences(dict.Keys, twin.Keys, dict.Values, twin.Values)));
        }
    }
}

干杯

[1] 更新背景见hereherehere

【讨论】:

  • -1:这不是Zip 所做的。此示例将使用 Concat 而不是 Zip 来完成您想要做的事情。
  • 我认为 OP 希望生成的序列有 6 个元素(5、25、6、36、7、49),而不是三个成对的元素。
  • @Jon - Concat 会给你 5,6,7,25,36,49。
  • @TrueWill:我知道——SelectMany 是这里的答案。但Concat 是我认为写这篇文章的人的想法。
  • 嘿嘿什么错误信息。 @Jon:Zip 是 not 连接的。 @Martinho:当场。顺便说一句,我在 as a comment here 之前发布了 selectmany 版本。将使用更好的信息 + 链接更新答案
【解决方案4】:

尝试使用以下方法:

var list = dictionary.Keys.ToList();
var list2 = dictionary.Values.ToList();

您可以将这些列表合二为一。

【讨论】:

    【解决方案5】:

    您可以使用 LINQ 创建对象/集合/您有什么。假设您想将两个非常不同/不相关(或几乎不相关)的项目合并为一个(伪代码如下):

    List<KeyValuePair<string, string>> newList = (from a in AList
                                                  select new KeyValuePair<string, string> 
                                                  {
                                                    a,
                                                    getBfromA(a)
                                                  });
    

    【讨论】:

      【解决方案6】:

      dict.Select(d => new[] { d.Key, d.Value }).SelectMany(d => d)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-20
        • 1970-01-01
        • 1970-01-01
        • 2021-03-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多