【问题标题】:Linq Aggregate complex types into a stringLinq 将复杂类型聚合成一个字符串
【发布时间】:2010-12-03 05:04:23
【问题描述】:

我已经看到 .net Aggregate 函数的简单示例是这样工作的:

string[] words = { "one", "two", "three" };
var res = words.Aggregate((current, next) => current + ", " + next);
Console.WriteLine(res);

如果您希望聚合更复杂的类型,如何使用“聚合”函数? 例如:一个具有 2 个属性的类,例如 'key' 和 'value',你想要这样的输出:

"MyAge: 33, MyHeight: 1.75, MyWeight:90"

【问题讨论】:

    标签: .net asp.net linq string-concatenation


    【解决方案1】:

    Aggregate 函数接受委托参数。您可以通过更改委托来定义您想要的行为。

    var res = data.Aggregate((current, next) => current + ", " + next.Key + ": " + next.Value);
    

    【讨论】:

    • 如果要聚合到源以外的类型,则需要指定种子。将“”指定为种子会编译,但结果将以“,”开头。
    【解决方案2】:

    Aggregate 有 3 个重载,因此您可以使用具有不同类型的一个来累积您要枚举的项目。

    您需要传入一个种子值(您的自定义类),以及一个将种子与一个值合并的方法。示例:

    MyObj[] vals = new [] { new MyObj(1,100), new MyObj(2,200), ... };
    MySum result = vals.Aggregate<MyObj, MySum>(new MySum(),
        (sum, val) =>
        {
           sum.Sum1 += val.V1;
           sum.Sum2 += val.V2;
           return sum;
        }
    

    【讨论】:

      【解决方案3】:

      你有两个选择:

      1. 投影到string,然后聚合:

        var values = new[] {
            new { Key = "MyAge", Value = 33.0 },
            new { Key = "MyHeight", Value = 1.75 },
            new { Key = "MyWeight", Value = 90.0 }
        };
        var res1 = values.Select(x => string.Format("{0}:{1}", x.Key, x.Value))
                        .Aggregate((current, next) => current + ", " + next);
        Console.WriteLine(res1);
        

        这样做的好处是使用第一个string 元素作为种子(没有前置“,”),但会为进程中创建的字符串消耗更多内存。

      2. 使用接受种子的聚合重载,可能是StringBuilder

        var res2 = values.Aggregate(new StringBuilder(),
            (current, next) => current.AppendFormat(", {0}:{1}", next.Key, next.Value),
            sb => sb.Length > 2 ? sb.Remove(0, 2).ToString() : "");
        Console.WriteLine(res2);
        

        第二个委托将我们的StringBuilder 转换为string,,使用条件修剪开始的“,”。

      【讨论】:

      • 完美,正是我想要的,所以我可以根据我的时间安排所有时间,滚动你自己的 for 循环会更快(我的测试中只有 1 或 2 个项目)
      • 由于列表中的项目如此之少,与更重要的解决方案相比,为 Select/Aggregate 设置“额外”枚举器的性能损失似乎相当严重。与大多数功能解决方案一样,问题是性能/可读性的权衡是否可以接受。鉴于大多数人对 Aggregate 的陌生程度,很容易得出结论,在这种情况下,命令式解决方案“更好”,与性能无关。
      • 两种方式都写完后,我同意了。聚合非常神秘,但它是我的盒子里的一个好工具;-)
      • 为什么不 var res1 = String.Join(",",values.Select(x => string.Format("{0}:{1}", x.Key, x.Value) ));
      • @Sean:因为 String.Join() 的重载直到 .NET 4 才存在。
      【解决方案4】:

      或者使用 string.Join() :

      var values = new[] {
          new { Key = "MyAge", Value = 33.0 },
          new { Key = "MyHeight", Value = 1.75 },
          new { Key = "MyWeight", Value = 90.0 }
      };
      var res = string.Join(", ", values.Select(item => $"{item.Key}: {item.Value}"));
      Console.WriteLine(res);
      

      【讨论】:

      • 这段代码运行良好,但没有回答关于聚合的问题。
      猜你喜欢
      • 1970-01-01
      • 2020-12-07
      • 1970-01-01
      • 1970-01-01
      • 2012-04-02
      • 1970-01-01
      • 1970-01-01
      • 2013-05-11
      相关资源
      最近更新 更多