C# 如何将 int[] 连接到 .NET 中的字符分隔字符串?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/145856/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to join int[] to a character separated string in .NET?
提问by Riri
I have an array of integers:
我有一个整数数组:
int[] number = new int[] { 2,3,6,7 };
What is the easiest way of converting these into a single string where the numbers are separated by a character (like: "2,3,6,7"
)?
将这些转换为单个字符串的最简单方法是什么,其中数字由字符分隔(例如:)"2,3,6,7"
?
I'm in C# and .NET 3.5.
我使用 C# 和 .NET 3.5。
采纳答案by aku
var ints = new int[] {1, 2, 3, 4, 5};
var result = string.Join(",", ints.Select(x => x.ToString()).ToArray());
Console.WriteLine(result); // prints "1,2,3,4,5"
EDIT: As of (at least) .NET 4.5,
编辑:从(至少).NET 4.5 开始,
var result = string.Join(",", ints.Select(x => x.ToString()).ToArray());
is equivalent to:
相当于:
var result = string.Join(",", ints);
EDIT:
编辑:
I see several solutions advertise usage of StringBuilder. Someone complaints that Join method should take an IEnumerable argument.
我看到几个解决方案宣传 StringBuilder 的使用。有人抱怨 Join 方法应该采用 IEnumerable 参数。
I'm going to disappoint you :) String.Join requires array for a single reason - performance. Join method needs to know the size of the data to effectively preallocate necessary amount of memory.
我会让你失望的 :) String.Join 需要数组的原因只有一个 - 性能。Join 方法需要知道数据的大小才能有效地预分配必要的内存量。
Here is a part of internal implementation of String.Join method:
下面是 String.Join 方法内部实现的一部分:
// length computed from length of items in input array and length of separator
string str = FastAllocateString(length);
fixed (char* chRef = &str.m_firstChar) // note than we use direct memory access here
{
UnSafeCharBuffer buffer = new UnSafeCharBuffer(chRef, length);
buffer.AppendString(value[startIndex]);
for (int j = startIndex + 1; j <= num2; j++)
{
buffer.AppendString(separator);
buffer.AppendString(value[j]);
}
}
I'm too lazy to compare performance of suggested methods. But something tells me that Join will win :)
我懒得比较建议方法的性能。但有些事情告诉我加入会赢:)
回答by JacquesB
String.Join(";", number.Select(item => item.ToString()).ToArray());
We have to convert each of the items to a String
before we can join them, so it makes sense to use Select
and a lambda expression. This is equivalent to map
in some other languages. Then we have to convert the resulting collection of string back to an array, because String.Join
only accepts a string array.
我们必须String
先将每个项目转换为 a,然后才能加入它们,因此使用Select
lambda 表达式是有意义的。这相当于map
在其他一些语言中。然后我们必须将生成的字符串集合转换回数组,因为String.Join
只接受字符串数组。
The ToArray()
is slightly ugly I think. String.Join
should really accept IEnumerable<String>
, there is no reason to restrict it to only arrays. This is probably just because Join
is from before generics, when arrays were the only kind of typed collection available.
该ToArray()
稍微难看,我认为。String.Join
应该真正接受IEnumerable<String>
,没有理由将其限制为仅数组。这可能只是因为Join
它来自泛型之前,当时数组是唯一可用的类型化集合。
回答by Joe
If your array of integers may be large, you'll get better performance using a StringBuilder. E.g.:
如果您的整数数组可能很大,则使用 StringBuilder 可以获得更好的性能。例如:
StringBuilder builder = new StringBuilder();
char separator = ',';
foreach(int value in integerArray)
{
if (builder.Length > 0) builder.Append(separator);
builder.Append(value);
}
string result = builder.ToString();
Edit: When I posted this I was under the mistaken impression that "StringBuilder.Append(int value)" internally managed to append the string representation of the integer value without creating a string object. This is wrong: inspecting the method with Reflector shows that it simply appends value.ToString().
编辑:当我发布这篇文章时,我错误地认为“StringBuilder.Append(int value)”在内部设法附加整数值的字符串表示而不创建字符串对象。这是错误的:使用 Reflector 检查该方法表明它只是附加了 value.ToString()。
Therefore the only potential performance difference is that this technique avoids one array creation, and frees the strings for garbage collection slightly sooner. In practice this won't make any measurable difference, so I've upvoted this better solution.
因此,唯一潜在的性能差异是这种技术避免了一个数组的创建,并且会更快地释放字符串以进行垃圾回收。在实践中,这不会产生任何可衡量的差异,所以我赞成这个更好的解决方案。
回答by Jon Skeet
One mixture of the two approaches would be to write an extension method on IEnumerable<T> which used a StringBuilder. Here's an example, with different overloads depending on whether you want to specify the transformation or just rely on plain ToString. I've named the method "JoinStrings" instead of "Join" to avoid confusion with the other type of Join. Perhaps someone can come up with a better name :)
这两种方法的一种混合是在使用 StringBuilder 的 IEnumerable<T> 上编写扩展方法。这是一个示例,根据您是要指定转换还是仅依赖普通 ToString,有不同的重载。我将方法命名为“JoinStrings”而不是“Join”以避免与其他类型的 Join 混淆。也许有人可以想出一个更好的名字:)
using System;
using System.Collections.Generic;
using System.Text;
public static class Extensions
{
public static string JoinStrings<T>(this IEnumerable<T> source,
Func<T, string> projection, string separator)
{
StringBuilder builder = new StringBuilder();
bool first = true;
foreach (T element in source)
{
if (first)
{
first = false;
}
else
{
builder.Append(separator);
}
builder.Append(projection(element));
}
return builder.ToString();
}
public static string JoinStrings<T>(this IEnumerable<T> source, string separator)
{
return JoinStrings(source, t => t.ToString(), separator);
}
}
class Test
{
public static void Main()
{
int[] x = {1, 2, 3, 4, 5, 10, 11};
Console.WriteLine(x.JoinStrings(";"));
Console.WriteLine(x.JoinStrings(i => i.ToString("X"), ","));
}
}
回答by DocMax
I agree with the lambda expression for readability and maintainability, but it will not always be the best option. The downside to using both the IEnumerable/ToArray and StringBuilder approaches is that they have to dynamically grow a list, either of items or characters, since they do not know how much space will be needed for the final string.
我同意 lambda 表达式的可读性和可维护性,但它并不总是最好的选择。使用 IEnumerable/ToArray 和 StringBuilder 方法的缺点是它们必须动态地增长一个列表,无论是项目还是字符,因为它们不知道最终字符串需要多少空间。
If the rare case where speed is more important than conciseness, the following is more efficient.
如果速度比简洁更重要的罕见情况,以下更有效。
int[] number = new int[] { 1, 2, 3, 4, 5 };
string[] strings = new string[number.Length];
for (int i = 0; i < number.Length; i++)
strings[i] = number[i].ToString();
string result = string.Join(",", strings);
回答by Ray Lu
You can do
你可以做
ints.ToString(",")
ints.ToString("|")
ints.ToString(":")
Check out
查看
Separator Delimited ToString for Array, List, Dictionary, Generic IEnumerable
回答by Will Dean
Although the OP specified .NET 3.5, people wanting to do this in .NET 2.0 with C#2 can do this:
尽管 OP 指定了 .NET 3.5,但想要在 .NET 2.0 中使用 C#2 执行此操作的人可以这样做:
string.Join(",", Array.ConvertAll<int, String>(ints, Convert.ToString));
I find there are a number of other cases where the use of the Convert.xxx functions is a neater alternative to a lambda, although in C#3 the lambda might help the type-inferencing.
我发现在许多其他情况下,使用 Convert.xxx 函数是 lambda 的更简洁的替代方案,尽管在 C#3 中,lambda 可能有助于类型推断。
A fairly compact C#3 version which works with .NET 2.0 is this:
一个适用于 .NET 2.0 的相当紧凑的 C#3 版本是这样的:
string.Join(",", Array.ConvertAll(ints, item => item.ToString()))
回答by void
ints.Aggregate("", ( str, n ) => str +","+ n ).Substring(1);
I also thought there was a simpler way. Don't know about performance, anyone has any (theoretical) idea?
我还认为有一个更简单的方法。不知道性能,有人有任何(理论上的)想法吗?
回答by WebMasterP
The question is for "easiest way of converting these in to a single string where the number are separated by a character".
问题是“将这些转换为单个字符串的最简单方法,其中数字由字符分隔”。
The easiest way is:
最简单的方法是:
int[] numbers = new int[] { 2,3,6,7 };
string number_string = string.Join(",", numbers);
// do whatever you want with your exciting new number string
EDIT: This only works in .NET 4.0+, I missed the .NET 3.5 requirement the first time I read the question.
编辑:这仅适用于 .NET 4.0+,我第一次阅读问题时错过了 .NET 3.5 要求。
回答by Stefan Steiger
In .NET 4.0, string join has an overload for params object[]
, so it's as simple as:
在 .NET 4.0 中,字符串连接对 有一个重载params object[]
,所以它很简单:
int[] ids = new int[] { 1, 2, 3 };
string.Join(",", ids);
example
例子
int[] ids = new int[] { 1, 2, 3 };
System.Data.Common.DbCommand cmd = new System.Data.SqlClient.SqlCommand("SELECT * FROM some_table WHERE id_column IN (@bla)");
cmd.CommandText = cmd.CommandText.Replace("@bla", string.Join(",", ids));
In .NET 2.0, it's a tiny little bit more difficult, since there's no such overload. So you need your own generic method:
在 .NET 2.0 中,它稍微有点困难,因为没有这样的过载。所以你需要你自己的通用方法:
public static string JoinArray<T>(string separator, T[] inputTypeArray)
{
string strRetValue = null;
System.Collections.Generic.List<string> ls = new System.Collections.Generic.List<string>();
for (int i = 0; i < inputTypeArray.Length; ++i)
{
string str = System.Convert.ToString(inputTypeArray[i], System.Globalization.CultureInfo.InvariantCulture);
if (!string.IsNullOrEmpty(str))
{
// SQL-Escape
// if (typeof(T) == typeof(string))
// str = str.Replace("'", "''");
ls.Add(str);
} // End if (!string.IsNullOrEmpty(str))
} // Next i
strRetValue= string.Join(separator, ls.ToArray());
ls.Clear();
ls = null;
return strRetValue;
}
In .NET 3.5, you can use extension methods:
在 .NET 3.5 中,您可以使用扩展方法:
public static class ArrayEx
{
public static string JoinArray<T>(this T[] inputTypeArray, string separator)
{
string strRetValue = null;
System.Collections.Generic.List<string> ls = new System.Collections.Generic.List<string>();
for (int i = 0; i < inputTypeArray.Length; ++i)
{
string str = System.Convert.ToString(inputTypeArray[i], System.Globalization.CultureInfo.InvariantCulture);
if (!string.IsNullOrEmpty(str))
{
// SQL-Escape
// if (typeof(T) == typeof(string))
// str = str.Replace("'", "''");
ls.Add(str);
} // End if (!string.IsNullOrEmpty(str))
} // Next i
strRetValue= string.Join(separator, ls.ToArray());
ls.Clear();
ls = null;
return strRetValue;
}
}
So you can use the JoinArray extension-method.
所以你可以使用 JoinArray 扩展方法。
int[] ids = new int[] { 1, 2, 3 };
string strIdList = ids.JoinArray(",");
You can also use that extension method in .NET 2.0, if you add the ExtensionAttribute to your code:
如果将 ExtensionAttribute 添加到代码中,您也可以在 .NET 2.0 中使用该扩展方法:
// you need this once (only), and it must be in this namespace
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)]
public sealed class ExtensionAttribute : Attribute {}
}