在C#中,我有一个仅包含数字的int数组,我希望将该数组转换为字符串。
数组示例:
数组示例:
int[] arr = {0,1,2,3,0,1};
我该如何将它转换为格式为"012301"
的字符串?
在.NET 3.5中使用:
String.Join("", new List<int>(array).ConvertAll(i => i.ToString()).ToArray());
在.net 4.0及以上版本中使用:(请参见@Jan Remunda的答案)
string result = string.Join("", array);
string.Empty
,因为它在内部使用了 StringBuilder
。string result = string.Join(string.Empty, new []{0,1,2,3,0,1});
例如:如果您使用分号作为分隔符,结果将是0;1;2;3;0;1
。string result = string.Join(null, new object[]{0,1,2,3,0,"A",DateTime.Now});
result = arr.Aggregate(string.Empty, (s, i) => s + i.ToString());
result = (arr == null) ? null : arr.Aggregate(string.Empty, (s, i) => s + i.ToString());
result = (arr == null) ? null : arr.Skip(1).Aggregate(arr[0].ToString(), (s, i) => s + "," + i.ToString());
这段代码还不算太糟糕,但我认为一眼看上去并不清楚它在做什么。
当然,你可以将这行代码放入自己的实用程序函数中,以便不必在应用逻辑中混杂着繁琐冗长的代码,特别是如果你在多个地方都使用此功能:
public static string ToStringLinqy<T>(this T[] array, string delimiter)
{
// edit: let's replace this with a "better" version using a StringBuilder
//return (array == null) ? null : (array.Length == 0) ? string.Empty : array.Skip(1).Aggregate(array[0].ToString(), (s, i) => s + "," + i.ToString());
return (array == null) ? null : (array.Length == 0) ? string.Empty : array.Skip(1).Aggregate(new StringBuilder(array[0].ToString()), (s, i) => s.Append(delimiter).Append(i), s => s.ToString());
}
但是如果您将其放入实用程序函数中,那么您真的需要将其压缩成一行吗?在这种情况下,为什么不添加几行以增加清晰度并利用StringBuilder,以便您不会执行重复的连接操作:
public static string ToStringNonLinqy<T>(this T[] array, string delimiter)
{
if (array != null)
{
// edit: replaced my previous implementation to use StringBuilder
if (array.Length > 0)
{
StringBuilder builder = new StringBuilder();
builder.Append(array[0]);
for (int i = 1; i < array.Length; i++)
{
builder.Append(delimiter);
builder.Append(array[i]);
}
return builder.ToString()
}
else
{
return string.Empty;
}
}
else
{
return null;
}
}
如果您非常关注性能,您甚至可以将其转换为混合函数,根据数组中有多少元素来决定是使用string.Join还是使用StringBuilder(这是一种微小的优化,在我看来并不值得做,可能会带来更多的负面影响而非好处,但我将其用作此问题的示例):
public static string ToString<T>(this T[] array, string delimiter)
{
if (array != null)
{
// determine if the length of the array is greater than the performance threshold for using a stringbuilder
// 10 is just an arbitrary threshold value I've chosen
if (array.Length < 10)
{
// assumption is that for arrays of less than 10 elements
// this code would be more efficient than a StringBuilder.
// Note: this is a crazy/pointless micro-optimization. Don't do this.
string[] values = new string[array.Length];
for (int i = 0; i < values.Length; i++)
values[i] = array[i].ToString();
return string.Join(delimiter, values);
}
else
{
// for arrays of length 10 or longer, use a StringBuilder
StringBuilder sb = new StringBuilder();
sb.Append(array[0]);
for (int i = 1; i < array.Length; i++)
{
sb.Append(delimiter);
sb.Append(array[i]);
}
return sb.ToString();
}
}
else
{
return null;
}
}
对于这个示例,性能影响可能不值得关注,但重点是,如果您处于情况之中,实际上需要关注操作的性能,无论这些操作是什么,那么使用实用函数处理它很可能比使用复杂的Linq表达式更容易和更可读。
那个实用函数看起来还有点笨重。现在让我们摒弃混合物,这样做:
// convert an enumeration of one type into an enumeration of another type
public static IEnumerable<TOut> Convert<TIn, TOut>(this IEnumerable<TIn> input, Func<TIn, TOut> conversion)
{
foreach (TIn value in input)
{
yield return conversion(value);
}
}
// concatenate the strings in an enumeration separated by the specified delimiter
public static string Delimit<T>(this IEnumerable<T> input, string delimiter)
{
IEnumerator<T> enumerator = input.GetEnumerator();
if (enumerator.MoveNext())
{
StringBuilder builder = new StringBuilder();
// start off with the first element
builder.Append(enumerator.Current);
// append the remaining elements separated by the delimiter
while (enumerator.MoveNext())
{
builder.Append(delimiter);
builder.Append(enumerator.Current);
}
return builder.ToString();
}
else
{
return string.Empty;
}
}
// concatenate all elements
public static string ToString<T>(this IEnumerable<T> input)
{
return ToString(input, string.Empty);
}
// concatenate all elements separated by a delimiter
public static string ToString<T>(this IEnumerable<T> input, string delimiter)
{
return input.Delimit(delimiter);
}
// concatenate all elements, each one left-padded to a minimum length
public static string ToString<T>(this IEnumerable<T> input, int minLength, char paddingChar)
{
return input.Convert(i => i.ToString().PadLeft(minLength, paddingChar)).Delimit(string.Empty);
}
int[] arr = { 0, 1, 2, 3, 0, 1 };
// 012301
result = arr.ToString<int>();
// comma-separated values
// 0,1,2,3,0,1
result = arr.ToString(",");
// left-padded to 2 digits
// 000102030001
result = arr.ToString(2, '0');
var builder = new StringBuilder();
Array.ForEach(arr, x => builder.Append(x));
var res = builder.ToString();
builder.Append
而不是 lambda 表达式,因为 builder.Append
与 Array.ForEach
中预期委托的签名匹配。 - Steve GuidiForEach()
期望的是 void
,而 Append()
返回的是 StringBuilder
。 - Danko Durbićstring result = arr.Aggregate("", (s, i) => s + i.ToString());
(免责声明:如果您有很多数字(至少数百个),并且在意性能,请避免使用此方法,而使用像JaredPar的答案中所述的StringBuilder
。)
int[] arr = {0,1,2,3,0,1};
string results = string.Join("",arr.Select(i => i.ToString()).ToArray());
我喜欢使用StringBuilder
和Aggregate()
。"诀窍"在于Append()
返回StringBuilder
实例本身:
var sb = arr.Aggregate( new StringBuilder(), ( s, i ) => s.Append( i ) );
var result = sb.ToString();
这是一个绕远路的方式,但代码量不大,容易让初学者理解。
int[] arr = {0,1,2,3,0,1};
string joined = "";
foreach(int i in arr){
joined += i.ToString();
}
int number = int.Parse(joined);
string s = string.Concat(arr.Cast<object>().ToArray());
string.Join("", (from i in arr select i.ToString()).ToArray())
string.Join
可以直接使用IEnumerable<string>
:string.Join("", from i in arr select i.ToString())