如何将int []与.NET中的字符分隔字符串连接?

时间:2020-03-06 14:50:44  来源:igfitidea点击:

我有一个整数数组:

int[] number = new int[] { 2,3,6,7 };

将这些内容转换为单个字符串(其中的数字用字符分隔)(例如:"" 2,3,6,7"`)的最简单方法是什么?

我在Cand .NET 3.5中。

解决方案

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"

编辑:

我看到一些解决方案宣传StringBuilder的用法。有人抱怨Jo​​in方法应该采用IEnumerable参数。

我会让我们失望的是:) String.Join出于唯一原因需要数组。 Join方法需要知道数据的大小,以有效地预分配必要的内存量。

这是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]);
    }
}

我太懒了,无法比较建议方法的性能。但是有件事告诉我,Join会赢:)

String.Join(";", number.Select(item => item.ToString()).ToArray());

我们必须先将每个项目转换为String才能加入它们,因此使用Select和lambda表达式是有意义的。这等效于其他一些语言中的" map"。然后我们必须将结果字符串集合转换回数组,因为String.Join只接受一个字符串数组。

我认为ToArray()有点难看。 String.Join应该真正接受IEnumerable &lt;String>,没有理由将其限制为仅数组。这可能是因为Join来自泛型之前,而数组是唯一可用的类型化集合。

如果整数数组可能很大,则使用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();

编辑:当我发布此内容时,我被误以为" StringBuilder.Append(int值)"内部设法在不创建字符串对象的情况下追加了整数值的字符串表示形式。这是错误的:使用Reflector检查该方法表明它只是添加了value.ToString()。

因此,唯一可能的性能差异是该技术避免了一个数组的创建,并稍早释放了用于垃圾回收的字符串。在实践中,这不会产生任何可衡量的变化,因此我赞成这种更好的解决方案。

两种方法的一种混合是在IEnumerable <T>上编写一个使用StringBuilder的扩展方法。这是一个示例,具有不同的重载,具体取决于我们是要指定转换还是仅依赖纯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"), ","));
    }
}

我同意lambda表达式的可读性和可维护性,但它并不总是最佳选择。同时使用IEnumerable / ToArray和StringBuilder方法的不利之处在于,它们必须动态地增加项目或者字符的列表,因为他们不知道最终字符串将需要多少空间。

如果在极少数情况下,速度比简洁更重要,那么以下效率会更高。

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);

你可以做

ints.ToString(",")
ints.ToString("|")
ints.ToString(":")

退房

分隔符分隔的ToString,用于数组,列表,字典,通用IEnumerable

尽管OP指定了.NET 3.5,但是希望在带有C#2的.NET 2.0中执行此操作的人可以执行以下操作:

string.Join(",", Array.ConvertAll<int, String>(ints, Convert.ToString));

我发现还有许多其他情况,其中Convert.xxx函数的使用是lambda的更巧妙的选择,尽管在C#3中,lambda可能有助于类型推断。

可以与.NET 2.0一起使用的相当紧凑的C#3版本是这样的:

string.Join(",", Array.ConvertAll(ints, item => item.ToString()))

ints.Aggregate("", ( str, n ) => str +","+ n ).Substring(1);

我还认为有一种更简单的方法。不了解性能,任何人都有(理论上的)想法吗?