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


101

我有一个整数数组:

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

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

我在C#和.NET 3.5中。


3
太棒了!我在星期日的10分钟内得到了这3个出色的答案!
Riri

4
从某种意义上说,.NET 4.0有些方法需要一个对象数组和一个IEnumerable,因此您可以这样做string.join(",", number)。我知道问题指定了.NET 3.5,所以我没有给出答案,但是它出现在未指定版本的搜索中,并且知道4.0中可能的版本可以帮助某人。
詹森·古玛

Answers:


162
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"

编辑:从(至少).NET 4.5开始,

var result = string.Join(",", ints.Select(x => x.ToString()).ToArray());

等效于:

var result = string.Join(",", ints);

编辑

我看到一些解决方案宣传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会赢:)


这可能是使用核心.NET扩展方法的最佳选择,但我确实希望string.Join()接受IEnumerable <string>以避免ToArray()转换。
spoulson

无法阻止某人重载字符串。也可以加入IEnumerable。;)
罗伯特·P

1
这可能也是最简单的解决方案,而不仅仅是最快的解决方案。
Dave Van den Eynde

9
.NET 4提供了String.Join重载,该重载接受IEnumerable作为参数。msdn.microsoft.com/en-us/library/dd783876.aspx
Ryan Kohn

using System.Linq;是必须的。
Gayan Weerakutti

32

尽管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()))

11

两种方法的一种混合是在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"), ","));
    }
}

不错的解决方案!不过,您不需要projection参数,只需编写x.Select(i => i.ToString(“ X”))。JoinStrings(“;”)就可以了。
雅克·B

是的,我后来考虑过。偶尔能够一次性指定所有内容很不错,但是拆分操作绝对更优雅:)
Jon Skeet

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

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

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


5

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

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


您测量过它更快了吗?String.Join也使用StringBuilder。
JacquesB

是的,但是您首先需要将整个对象转换为数组,这远非理想。特别是,这意味着开始生成结果字符串之前,您需要同时将所有转换后的字符串存储在内存中。
Jon Skeet

OTOH String.Join会预先计算StringBuilder缓冲区的大小,从而避免调整大小。因此,即使需要更多内存,它也会更快。
JacquesB

5

问题是“将它们转换成单个字符串的最简单方法,其中数字用字符分隔”。

最简单的方法是:

int[] numbers = new int[] { 2,3,6,7 };
string number_string = string.Join(",", numbers);
// do whatever you want with your exciting new number string

编辑:这仅在.NET 4.0+中有效,我第一次阅读问题时就错过了.NET 3.5要求。


这不是有效的string.Join方法仅接受一个字符串数组。在这里看看msdn.microsoft.com/en-us/library/tk0xe5h0.aspx
ppolyzos 2011年

1
这是一个重载的方法: msdn.microsoft.com/zh-cn/library/dd988350我只是将编写的代码复制到新的控制台应用程序中,添加了Console.WriteLine,这是输出:2,3,6,7
WebMasterP

1
我认为只能在.net 4中使用
Govind Malviya 2012年

需要一个对象数组(或字符串数​​组),而不是一个int数组。会给出“通话不明确”的错误。
LarryBud 2015年

2

我同意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);

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

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


该解决方案将为您提供“,1,2,3,4,5”。
沙林2010年

谢谢,我已经添加Substring(1)了修复程序(它来自内存)。
无效

2

在.NET 4.0中,字符串连接具有的重载params object[],因此很简单:

int[] ids = new int[] { 1, 2, 3 };
string.Join(",", ids);

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

在.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;
}

在.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;
    }

}

因此,您可以使用JoinArray扩展方法。

int[] ids = new int[] { 1, 2, 3 };
string strIdList = ids.JoinArray(",");

如果将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 {}
}

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.