C#/ LINQ:连接字符串

时间:2011-07-14 16:34:22

标签: c# linq functional-programming

是否有更好的功能,简洁或优雅的方式来写这个?减少/折叠功能,也许?

var key = String.Join(String.Empty,
    new[] {
        keyRoot,
        controllerName,
        actionName
    }.Concat(
        from param in params
        select param.Key + param.Value
    )
);

输入是一些字符串变量,以及来自Dictionary<string, string>的连续键/值的可枚举。

输出应该是所有连接的字符串。

6 个答案:

答案 0 :(得分:3)

听起来你可以使用LINQ Aggregate函数:

Using LINQ to concatenate strings

答案 1 :(得分:1)

对我来说更具可读性是这样的:

string key = string.Format("{0}{1}{2}{3}", 
                            keyRoot, 
                            controllerName, 
                            actionName, 
                            string.Join(string.Empty, parameters.Select( p =>  p.Key + p.Value)));

这可能不像&#34;功能性&#34;但肯定会像我能想出的那样简洁明了。

答案 2 :(得分:0)

这并没有太多改善......

var key = string.Concat(
   new[] {
    keyRoot,
    controllerName,
    actionName
   }.Concat(
       params.Select(kvp) => param.Key + param.Value)
   ).ToArray ()
);

如果它不必是单个陈述,则缩短2行。

var list = new List<String> {
    keyRoot,
    controllerName,
    actionName
   };
list.AddRange (params.Select(kvp) => param.Key + param.Value));
var key = string.Concat(list.ToArray ());

答案 3 :(得分:0)

扩展为StringBuilder

public static class StringBuilderExtensions {

  public static StringBuilder AppendAll(this StringBuilder builder, IEnumerable<string> strings) {
    foreach (string s in strings) builder.Append(s);
    return builder;
  }

}

它变得相当简短和有效:

string key =
  new StringBuilder()
  .Append(keyRoot)
  .Append(controllerName)
  .Append(actionName)
  .AppendAll(parameters.Select(p => p.Key + p.Value))
  .ToString();

这将构建字符串而不创建任何中间数组。

要改进的一件事是通过将键和值直接添加到p.Key + p.Value来避免间歇性字符串StringBuilder,但随后代码的可重用性降低。

要改进的另一件事是设置StringBuilder的容量,但是你需要循环遍历字典并首先添加字符串的长度。

(注意:我使用parameters作为字典名称而不是params,因为这是一个关键字。)

答案 4 :(得分:0)

我认为,为了连接所有字符串的序列,你的构造已经尽可能的功能了。

我可能不会将String.Join与空字符串一起使用,而是使用StringBuilderForEach扩展方法,例如

public static class MyExtensions {
  public static void ForEach(this IEnumerable<T> enumerable, Action<T> action) {
    foreach (var entry in enumerable)
      action(entry);
  }
}

我还会为序列定义一个局部变量,如

var seq = new[] {
                   keyRoot,
                   controllerName,
                   actionName
          }.Concat(
           from param in params select param.Key + param.Value
          );
var sb = new StringBuilder();
seq.ForEach(s=>sb.Append(s));

当然,使用Aggregate函数会更“实用”,但在我看来它不具有可读性,而且还有性能损失,因为你需要构造中间字符串......

答案 5 :(得分:0)

以下是使用Aggregate(实际上是折叠)的一个表达式中的解决方案:

var key = params.Aggregate(new StringBuilder()
    .Append(keyRoot)
    .Append(controllerName)
    .Append(actionName),
    (sb, p) => sb.Append(p.Key).Append(p.Value))
    .ToString();