私は整数の配列を持っています:
int[] number = new int[] { 2,3,6,7 };
これらを数字で区切られた単一の文字列に変換する最も簡単な方法は何ですか(たとえば:"2,3,6,7"
)?
私はC#と.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"
[〜#〜] edit [〜#〜]:(少なくとも).NET 4.5以降、
var result = string.Join(",", ints.Select(x => x.ToString()).ToArray());
以下と同等です:
var result = string.Join(",", ints);
[〜#〜] edit [〜#〜]:
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が勝つことを教えてくれます:)
OPは.NET 3.5を指定しましたが、C#2を使用して.NET 2.0でこれを実行したい人はこれを実行できます。
string.Join(",", Array.ConvertAll<int, String>(ints, Convert.ToString));
Convert.xxx関数の使用がラムダに代わるきれいな代替である他の多くのケースがありますが、C#3ではラムダが型推論を助けるかもしれません。
.NET 2.0で動作するかなりコンパクトなC#3バージョンは次のとおりです。
string.Join(",", Array.ConvertAll(ints, item => item.ToString()))
2つのアプローチの1つの混合は、StringBuilderを使用するIEnumerable <T>に拡張メソッドを記述することです。次に例を示します。変換を指定するか、単純なToStringに依存するかによって、オーバーロードが異なります。他の種類のJoinとの混同を避けるために、メソッドに「Join」ではなく「JoinStrings」という名前を付けました。おそらく誰かがより良い名前を思いつくことができます:)
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"), ","));
}
}
_String.Join(";", number.Select(item => item.ToString()).ToArray());
_
各項目を結合する前にString
に変換する必要があるため、Select
とラムダ式を使用することは理にかなっています。これは、他の言語のmap
と同等です。 _String.Join
_は文字列配列のみを受け入れるため、結果の文字列のコレクションを変換して配列に戻す必要があります。
ToArray()
は少しslightlyいと思います。 _String.Join
_は実際に_IEnumerable<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 value)」は文字列オブジェクトを作成せずに整数値の文字列表現を内部で追加できたという誤った印象を受けていました。これは間違っています。Reflectorでメソッドを調べると、value.ToString()が単に追加されていることがわかります。
したがって、唯一の潜在的なパフォーマンスの違いは、この手法が1つの配列の作成を回避し、ガベージコレクション用の文字列を少し早く解放することです。実際には、これは測定可能な違いをもたらさないので、私は このより良い解決策 を支持しました。
問題は、「これらを数字で区切られた単一の文字列に変換する最も簡単な方法」です。
最も簡単な方法は次のとおりです。
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の要件を逃しました。
.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 {}
}
可読性と保守性についてはラムダ式に同意しますが、常に最良の選択肢とは限りません。 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.Aggregate("", ( str, n ) => str +","+ n ).Substring(1);
また、もっと簡単な方法があると思いました。パフォーマンスについて知らない、誰もが(理論的な)アイデアを持っていますか?
できるよ
ints.ToString(",")
ints.ToString("|")
ints.ToString(":")
チェックアウト