【问题标题】:Fastest way to convert a list of strings into a single concatenated string?将字符串列表转换为单个连接字符串的最快方法?
【发布时间】:2023-03-03 18:16:01
【问题描述】:

我有一些生成字符串列表的 LINQ 代码,如下所示:

var data = from a in someOtherList
           orderby a
           select FunctionThatReturnsString(a);

如何将该字符串列表转换为一个大的串联字符串?假设数据有这些条目:

"Some "
"resulting "
"data here."

我应该得到一个如下所示的字符串:

"Some resulting data here."

我怎样才能快速做到这一点?我想到了这个:

StringBuilder sb = new StringBuilder();
data.ToList().ForEach(s => sb.Append(s));
string result = sb.ToString();

但这似乎并不正确。如果这是正确的解决方案,我将如何将其转变为扩展方法?

【问题讨论】:

    标签: c# string extension-methods linq-to-objects


    【解决方案1】:

    怎么样:

    public static string Concat(this IEnumerable<string> source) {
        StringBuilder sb = new StringBuilder();
        foreach(string s in source) {
            sb.Append(s);
        }
        return sb.ToString();
    }
    

    和:

    string s = data.Concat();
    

    这样就不需要额外的ToList() / ToArray() 步骤。

    【讨论】:

    • +1 这不是最短的方法,但 OP 显然要求 fastest,这确实优于使用 ToArray() 跟随 string.Concat/@987654327 @.
    • @Noldorin: 最快的有点不确定 ;) 对于程序员或机器?
    • 谢谢!我所说的最快是指运行时间。
    • @jasonh:如果速度是问题,在列表中进行两次传递会更快,第一次计算总长度以便可以预先分配 StringBuilder。
    • @jasonh:我刚刚对其进行了测试,它按预期工作。你的问题的原因是别的。 Marc 代码采用单个参数,该参数将成为隐式,因为它是一种扩展方法,但 MS 版本采用 2 个参数(其中一个是隐式传递的)。他们可以幸福地生活在一起。
    【解决方案2】:

    您尝试过 String.Join 吗?如果您已经愿意承担 .ToList 调用的开销,那么请改用 .ToArray() 并将其与对 String.Join 的调用结合起来。

    var joined = String.Concat(someQuery.ToArray());
    

    注意:我的解决方案可能不是最快的,因为它涉及到数组中的一些开销。我的怀疑是走更多马克的路线会更快。但在大多数情况下,如果您只是在寻找快速而肮脏的代码方式,那么我的路线将起作用。

    【讨论】:

    • 有什么理由不使用string.Concat
    • @Mehrdad,不,Join 只是今天我脑海中浮现的第一个。
    • 在我的测试中,性能与 Marc 的解决方案并驾齐驱(适用于各种字符串和集合长度),所以你得到我的投票。
    【解决方案3】:

    像这样使用“聚合”:

        List<string> strings = new List<string>() {"bob", "steve", "jane"};
        string result = strings.Aggregate((working, next) => working + next);
        Console.WriteLine(result);
    

    注意:Aggregate 作为扩展方法位于 System.Linq 命名空间中。

    【讨论】:

      【解决方案4】:
      data.ToList().Aggregate(new StringBuilder(), (sb, s) => sb.Append(s)).ToString();
      

      【讨论】:

        【解决方案5】:

        您可以使用此语句。 String.Join("",someOtherList);

        【讨论】:

        • 你能再解释一下吗?
        • 也许不是最快,但最简单!
        【解决方案6】:

        根据 JIT 的优化方式,使用 StringBuilder 的 string.Concat() 或 Marc 方法可能会更快。由于您在这里使用 Linq,我假设性能不是绝对的 #1 要求,在这种情况下,我会选择最容易阅读的:

        string.Concat(data.ToArray());
        

        编辑:当且仅当数据是 值类型的 IEnumerable 时,您需要将其强制转换为 IEnumerable

        string.Concat(data.Cast<object>().ToArray())
        

        编辑 2:我并不是说 Linq 很慢。我只是说我提到的两种方式之间的速度差异应该是非常小的,即使是可以测量的。

        编辑 3:JIT 优化了几乎所有对 String 类的操作,因此对 string.Concat 的内部运行时的单个调用确实比使用 StringBuilder 更快。我不确定它是不是,但你应该测试它以确保。

        【讨论】:

        • 从什么时候开始Linq已经相当于slow了?
        • 你为什么要做data.Cast&lt;object&gt;()而不是data.Select(x =&gt; x.ToString())
        • string 有一个成员 string.Concat(object[] args) 很可能更有效地执行内部 ToString 操作。您需要强制转换为 object 的唯一原因是值类型数组(如 int[])不能隐式转换为 object[]。
        • Concat(object[]) 重载只是在内部调用标准的ToString 方法。如果您自己对值类型执行ToString 操作,而不是使用Cast 将它们装箱,则可以使用Concat(string[]) 重载。
        【解决方案7】:

        替代方案:

        >>> data = ['Some ', 'resulting ', 'data here.']
        >>> s = ''.join(data)
        >>> s
        'Some resulting data here.'
        

        【讨论】:

          猜你喜欢
          • 2013-10-21
          • 2014-06-08
          • 1970-01-01
          • 2012-02-04
          • 2014-04-19
          • 2013-01-24
          • 2015-08-27
          • 1970-01-01
          相关资源
          最近更新 更多