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で可能であることが誰かを助けることができることを知っています。
Jason Goemaat 2015

回答:


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の使用法を宣伝しています。Joinメソッドが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()変換を回避することを望みました。
スポールソン2008

誰かが文字列をオーバーロードするのを防ぐものは何もありません。IEnumerableを取得するために参加します。;)
ロバートP

1
これはおそらく最も簡単な解決策であり、最速ではありません。
Dave Van den Eynde

9
.NET 4は、IEnumerableをパラメーターとして受け入れるString.Joinオーバーロードを提供します。msdn.microsoft.com/en-us/library/dd783876.aspx
ライアンコーン

using System.Linq;必要とされている。
Gayan Weerakutti、2018

32

OPは.NET 3.5を指定していましたが、C#2を使用した.NET 2.0でこれを実行したい人はこれを実行できます。

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

C#3ではラムダが型推論に役立つかもしれませんが、Convert.xxx関数の使用がラムダのより優れた代替手段である他の多くの場合があります。

.NET 2.0で動作するかなりコンパクトなC#3バージョンは次のとおりです。

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

11

2つのアプローチの1つの混合は、StringBuilderを使用するIEnumerable <T>で拡張メソッドを記述することです。以下に例を示します。変換を指定するか、単純なToStringに依存するかによって、オーバーロードが異なります。他のタイプの結合との混同を避けるために、「結合」の代わりに「結合文字列」という名前を付けました。たぶん誰かがもっと良い名前を思いつくかもしれません:)

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"), ","));
    }
}

素敵な解決策!ただし、プロジェクションパラメータは不要です。x.Select(i => i.ToString( "X"))。JoinStrings( ";")と書くだけで、より慣用的になります。
JacquesB 2008

はい、後で考えました。たまにすべてを一度に指定できるのはいいことですが、操作を分割する方が間違いなくエレガントです:)
Jon Skeet

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

String結合する前に各項目をa に変換する必要があるのでSelect、ラムダ式を使用するのが理にかなっています。これは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 value)"が内部的に管理して、文字列オブジェクトを作成せずに整数値の文字列表現を追加するという誤った印象を受けました。これは誤りです。Reflectorでメソッドを検査すると、単にvalue.ToString()が追加されていることがわかります。

したがって、唯一の潜在的なパフォーマンスの違いは、この手法は1つの配列の作成を回避し、ガベージコレクションのために文字列を少し早く解放することです。実際には、これは測定可能な違いをもたらさないので、私はこのより良いソリューションを支持しました


より速くなるように測定しましたか?String.JoinもStringBuilderを使用します。
JacquesB 2008

はい。ただし、最初に全体を配列に変換する必要がありますが、これは理想とはかけ離れています。特に、結果の文字列の作成を開始する前に、変換されたすべての文字列を同時にメモリに格納する必要があることを意味します。
ジョンスキート

OTOH String.Joinは、StringBuilderバッファーのサイズを事前計算して、サイズ変更を回避します。したがって、より多くのメモリが必要な場合でも、より高速になる可能性があります。
JacquesB 2008

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の要件を満たしていません。


これは文字列としては無効です。Joinメソッドは文字列の配列のみを取ります。こちらをご覧持っmsdn.microsoft.com/en-us/library/tk0xe5h0.aspx
ppolyzos

1
これはオーバーロードされたメソッドです: msdn.microsoft.com/en-us/library/dd988350私が書いたコードを新しいコンソールアプリにコピーし、Console.WriteLineを追加しました。これが出力です:2,3,6,7
WebMasterP 2012

1
これは.net 4でのみ利用可能だと思います
Govind Malviya '27 / 10/27

int配列ではなく、オブジェクト配列(または文字列配列)が必要です。「呼び出しがあいまいです」エラーが発生します。
LarryBud

2

読みやすさと保守性の観点からラムダ式に同意しますが、それが常に最良の選択肢であるとは限りません。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"が得られます。
Sarin

おかげで、それSubstring(1)を修正するために追加しました(メモリからのものです)。
2010

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 {}
}

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.