【问题标题】:How to flatten the result of a nested split in a C# Lambda expression如何展平 C# Lambda 表达式中嵌套拆分的结果
【发布时间】:2013-04-19 01:21:42
【问题描述】:

给定字符串“a:b;c:d,e;f:g,h,i”,我想将字符串拆分为包含两列的平面列表,每一列用于键(左侧冒号)和值(逗号分隔在冒号的右侧)。结果应该是这样的。

{
    Key: "a",
    Value: "b"
},
{
    Key: "c",
    Value: "d"
},
{
    Key: "c",
    Value: "e"
},
{
    Key: "f",
    Value: "g"
},
{
    Key: "f",
    Value: "h"
},
{
    Key: "f",
    Value: "i"
}

问题是我无法将第二次拆分在所有键上的逗号结果展平,因此我返回一个 KeyValue 列表,而不是 KeyValue 列表的列表。

public class KeyValue {
    public string Key { get; set; }
    public string Value { get; set; }
}

List<KeyValue> mc = "a:b;c:d,e;f:g,h,i"
    .Split(';')
    .Select(a =>
    {
        int colon = a.IndexOf(':');
        string left = a.Substring(0, colon);
        string right = a.Substring(colon + 1);
        List<KeyValue> result = right.Split(',').Select(x => new KeyValue { Key = left, Value = x }).ToList();
        return result;
    })
    .ToList();

感谢您的帮助。

【问题讨论】:

  • 为什么要一个KeyValue的列表?您的示例只是 KeyValue 的列表。
  • @SamLeach,我只想要一个 KeyValue 列表,但请注意,该值是 CSV 中以逗号分隔的冒号右侧的各个值。

标签: c# lambda


【解决方案1】:

您非常接近。将序列序列展平的方法是SelectMany。我们可以在您现有代码的末尾添加一个,但由于它已经以 Select 结尾,我们实际上可以将其更改为 SelectMany,我们就完成了:

List<KeyValue> mc = "a:b;c:d,e;f:g,h,i"
    .Split(';')
    .SelectMany(a =>
    {
        int colon = a.IndexOf(':');
        string left = a.Substring(0, colon);
        string right = a.Substring(colon + 1);
        List<KeyValue> result = right.Split(',')
            .Select(x => new KeyValue { Key = left, Value = x }).ToList();
        return result;
    })
    .ToList();

【讨论】:

    【解决方案2】:
    List<KeyValue> mc = "a:b;c:d,e;f:g,h,i"
        .Split(';')
        .Select(a =>
        {
            int colon = a.IndexOf(':');
            string left = a.Substring(0, colon);
            string right = a.Substring(colon + 1);
            return new KeyValue() { Key = left, Value = right };
        })
        .ToList();
    

    编辑:

    为了澄清,Select 将列表投射到新类型上;它已经为您处理了List 创建。因此,您要求 List 的 List 对象。您只需要询问对象,在本例中为 KeyValue。

    【讨论】:

    • 我认为您的解决方案缺少Value = right 上的第三个拆分,还是我遗漏了什么?
    【解决方案3】:

    您无需返回新的List&lt;KeyValue&gt; result。您只想返回KeyValue,如下所示

    string data = "a:b;c:d,e;f:g,h,i";
    
    var mc = data
        .Split(';')
        .Select(a =>
        {
            int colon = a.IndexOf(':');
            string left = a.Substring(0, colon);
            string right = a.Substring(colon + 1);
            return new KeyValue() { Key = left, Value = right };
        }).ToList();
    

    【讨论】:

    • 我认为您的解决方案缺少Value = right 上的第三个拆分,还是我遗漏了什么?
    【解决方案4】:

    和往常一样,它可以通过 Linq 执行:

    string s = "a:b;c:d,e;f:g,h,i";
    string Last = "";
    var Result = s.Split(';', ',').Select(x =>
    {
        if (x.Contains(":"))
        {
            Last = x.Split(':')[0];
            return new { Key = x.Split(':')[0], Value = x.Split(':')[1] };
        }
        else return new { Key = Last, Value = x };
    });
    

    【讨论】:

      【解决方案5】:
      string data = "a:b;c:d,e;f:g,h,i";
      
      var mc = data
          .Split(';')
          .SelectMany(x => {
              int separatorIndex = x.IndexOf(':');
              var key = x.Substring(0, separatorIndex);
              var values = x.Substring(separatorIndex + 1).Split(',');
      
              return values.Select(v => new KeyValuePair<string,string>(key, v));
          });
      

      【讨论】:

        猜你喜欢
        • 2020-03-20
        • 1970-01-01
        • 2020-07-07
        • 2017-05-08
        • 1970-01-01
        • 2011-09-19
        • 2016-07-13
        • 1970-01-01
        相关资源
        最近更新 更多