使用 LINQ 连接字符串
在 LINQ 中编写老式的:
StringBuilder sb = new StringBuilder();
if (strings.Count > 0)
{
foreach (string s in strings)
{
sb.Append(s + ", ");
}
sb.Remove(sb.Length - 2, 2);
}
return sb.ToString();
... 的最有效方法是什么?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(17)
这是我在查看其他答案和类似问题中解决的问题后决定采用的组合 Join/Linq 方法(即聚合和连接因 0 个元素而失败)。
string Result = String.Join(",", split.Select(s => s.Name));
或(如果
s
不是字符串)string Result = String.Join(",", split.Select(s => s.ToString()));
StringBuilder
)来实现当然Join 处理了有时会潜入其他方法中的讨厌的最后逗号(
for
、foreach
),这就是我首先寻找 Linq 解决方案的原因。Here is the combined Join/Linq approach I settled on after looking at the other answers and the issues addressed in a similar question (namely that Aggregate and Concatenate fail with 0 elements).
string Result = String.Join(",", split.Select(s => s.Name));
or (if
s
is not a string)string Result = String.Join(",", split.Select(s => s.ToString()));
StringBuilder
) to implementAnd of course Join takes care of the pesky final comma that sometimes sneaks into other approaches (
for
,foreach
), which is why I was looking for a Linq solution in the first place.这里有很多选择。 您可以使用 LINQ 和 StringBuilder,这样您也可以获得性能,如下所示:
Lots of choices here. You can use LINQ and a StringBuilder so you get the performance too like so:
您可以非常有效地将 LINQ 和 string.join() 结合起来。 在这里,我从字符串中删除一个项目。 还有更好的方法可以做到这一点,但这里是:
You can combine LINQ and
string.join()
quite effectively. Here I am removing an item from a string. There are better ways of doing this too but here it is:在使用 linq 解析 IIS 日志文件时,我做了以下快速而肮脏的操作,它在 100 万行时工作得很好(15 秒),尽管在尝试 200 万行时出现内存不足错误。
我使用 linq 的真正原因是为了我之前需要的 Distinct() :
I did the following quick and dirty when parsing an IIS log file using linq, it worked @ 1 million lines pretty well (15 seconds), although got an out of memory error when trying 2 millions lines.
The real reason I used linq was for a Distinct() I neede previously:
FWIW 我使用 BDN 对 15 个字符串的字符串数组进行了
string.Join
与.Aggregate
的基准测试:阵列越大,差距越大
FWIW I benchmarked
string.Join
vs.Aggregate
on a string array of 15 strings using BDN:The gap increases with bigger arrays
我不久前在博客上谈到了这一点,我所做的正是您正在寻找的:
http://ondevelopment.blogspot.com/2009/02/string-concatenation-made-easy.html
在博客文章中描述如何实现适用于 IEnumerable 和被命名为 Concatenate,这将允许您编写如下内容:
或更复杂的内容,例如:
I blogged about this a while ago, what I did seams to be exactly what you're looking for:
http://ondevelopment.blogspot.com/2009/02/string-concatenation-made-easy.html
In the blog post describe how to implement extension methods that works on IEnumerable and are named Concatenate, this will let you write things like:
Or more elaborate things like:
在 .Net 4 中,
字符串有一个新的重载。 Join
接受IEnumerable
。 代码将如下所示:In .Net 4, there's a new overload for
string.Join
that acceptsIEnumerable<string>
. The code would then look like:为什么使用 Linq?
据我所知,它完美地工作并接受任何
IEnumerable
。 这里不需要聚合
任何东西,这要慢得多。Why use Linq?
That works perfectly and accepts any
IEnumerable<string>
as far as I remember. No needAggregate
anything here which is a lot slower.您看过聚合扩展方法吗?
Have you looked at the Aggregate extension method?
我的代码中的真实示例:
查询是一个具有 Name 属性的对象,该属性是一个字符串,我想要所选列表上所有查询的名称,以逗号分隔。
Real example from my code:
A query is an object that has a Name property which is a string, and I want the names of all the queries on the selected list, separated by commas.
此答案显示了问题中要求的 LINQ (
Aggregate
) 的用法,并不适合日常使用。 因为这不使用 StringBuilder,所以对于很长的序列来说,它的性能会很糟糕。 对于常规代码,请使用String.Join
,如其他答案使用聚合像这样的查询:
输出:
聚合是一个函数,它接受值的集合并返回标量值。 T-SQL 的示例包括最小值、最大值和总和。 VB 和 C# 都支持聚合。 VB 和 C# 都支持聚合作为扩展方法。 使用点表示法,只需调用 IEnumerable< 上的方法即可/a> 对象。
请记住,聚合查询会立即执行。
详细信息 - MSDN:聚合查询
如果您确实想使用
Aggregate
使用 StringBuilder 使用变体>CodeMonkeyKing 与常规String.Join
的代码大致相同,包括对大量对象的良好性能:This answer shows usage of LINQ (
Aggregate
) as requested in the question and is not intended for everyday use. Because this does not use aStringBuilder
it will have horrible performance for very long sequences. For regular code useString.Join
as shown in the other answerUse aggregate queries like this:
This outputs:
An aggregate is a function that takes a collection of values and returns a scalar value. Examples from T-SQL include min, max, and sum. Both VB and C# have support for aggregates. Both VB and C# support aggregates as extension methods. Using the dot-notation, one simply calls a method on an IEnumerable object.
Remember that aggregate queries are executed immediately.
More information - MSDN: Aggregate Queries
If you really want to use
Aggregate
use variant usingStringBuilder
proposed in comment by CodeMonkeyKing which would be about the same code as regularString.Join
including good performance for large number of objects:StringBuilder 与 Select 和 Select 的快速性能数据 超过 3000 个元素的聚合案例:
单元测试 - 持续时间(秒)
LINQ_StringBuilder - 0.0036644
LINQ_Select.Aggregate - 1.8012535
quick performance data for the StringBuilder vs Select & Aggregate case over 3000 elements:
Unit test - Duration (seconds)
LINQ_StringBuilder - 0.0036644
LINQ_Select.Aggregate - 1.8012535
您可以在
Aggregate
中使用StringBuilder
:(其中的
Select
只是为了表明您可以执行更多 LINQ 操作。)You can use
StringBuilder
inAggregate
:(The
Select
is in there just to show you can do more LINQ stuff.)我将稍微作弊并给出一个新的答案,它似乎总结了这里最好的一切,而不是把它放在评论中。
因此,您可以这样一行:
编辑:您要么想首先检查空枚举,要么添加
.Replace("\a",string.Empty);
到表达式的末尾。 我想我可能是想变得有点太聪明了。@a.friend 的答案可能性能稍好一些,我不确定替换与删除相比在幕后做了什么。 唯一的其他警告,如果出于某种原因你想连接以 \a 结尾的字符串,你会丢失分隔符......我发现这不太可能。 如果是这种情况,您确实有 其他奇特的角色可供选择。
I'm going to cheat a little and throw out a new answer to this that seems to sum up the best of everything on here instead of sticking it inside of a comment.
So you can one line this:
Edit: You'll either want to check for an empty enumerable first or add an
.Replace("\a",string.Empty);
to the end of the expression. Guess I might have been trying to get a little too smart.The answer from @a.friend might be slightly more performant, I'm not sure what Replace does under the hood compared to Remove. The only other caveat if some reason you wanted to concat strings that ended in \a's you would lose your separators... I find that unlikely. If that is the case you do have other fancy characters to choose from.
这里它使用纯 LINQ 作为单个表达式:
而且速度非常快!
Here it is using pure LINQ as a single expression:
And its pretty damn fast!
通过“超级酷的 LINQ 方式”,您可能会谈论 LINQ 通过使用扩展方法使函数式编程变得更加容易接受的方式。 我的意思是,语法糖允许函数以视觉上线性的方式链接(一个接一个),而不是嵌套(一个在另一个里面)。 例如:
可以这样写:
你可以看到第二个例子如何更容易阅读。 您还可以看到如何添加更多函数,同时减少缩进问题或表达式末尾出现的 Lispy 右括号。
许多其他答案都指出
String.Join
是可行的方法,因为它是最快或最简单的读取方式。 但是,如果您接受我对“超酷 LINQ 方式”的解释,那么答案是使用 String.Join,但将其包装在 LINQ 样式扩展方法中,这样可以允许您可以以视觉上令人愉悦的方式链接您的功能。 因此,如果您想编写sa.Concatenate(", ")
您只需创建如下内容:这将提供与直接调用一样高性能的代码(至少在算法复杂性方面) )并且在某些情况下可能会使代码更具可读性(取决于上下文),特别是当块中的其他代码使用链式函数样式时。
By 'super-cool LINQ way' you might be talking about the way that LINQ makes functional programming a lot more palatable with the use of extension methods. I mean, the syntactic sugar that allows functions to be chained in a visually linear way (one after the other) instead of nesting (one inside the other). For example:
can be written like this:
You can see how the second example is easier to read. You can also see how more functions can be added with less of the indentation problems or the Lispy closing parens appearing at the end of the expression.
A lot of the other answers state that the
String.Join
is the way to go because it is the fastest or simplest to read. But if you take my interpretation of 'super-cool LINQ way' then the answer is to useString.Join
but have it wrapped in a LINQ style extension method that will allow you to chain your functions in a visually pleasing way. So if you want to writesa.Concatenate(", ")
you just need to create something like this:This will provide code that is as performant as the direct call (at least in terms of algorithm complexity) and in some cases may make the code more readable (depending on the context) especially if other code in the block is using the chained function style.
我总是使用扩展方法:
I always use the extension method: