Mam tablicę liczb całkowitych:
int[] number = new int[] { 2,3,6,7 };
Jaki jest najłatwiejszy sposób przekształcenia ich w pojedynczy ciąg, w którym liczby są oddzielone znakiem (na przykład "2,3,6,7"
:)?
Jestem w C # i .NET 3.5.
Mam tablicę liczb całkowitych:
int[] number = new int[] { 2,3,6,7 };
Jaki jest najłatwiejszy sposób przekształcenia ich w pojedynczy ciąg, w którym liczby są oddzielone znakiem (na przykład "2,3,6,7"
:)?
Jestem w C # i .NET 3.5.
.NET 4.0
istnieją metody, które pobierają tablicę obiektów i IEnumerable, więc możesz to zrobić string.join(",", number)
. Wiem, że pytanie określa .NET 3.5, więc nie udzieliłem odpowiedzi, ale pojawia się w wyszukiwaniach, które nie określają wersji, a wiedza, że jest to możliwe w 4.0, może komuś pomóc.
Odpowiedzi:
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"
EDYCJA : od (przynajmniej) .NET 4.5,
var result = string.Join(",", ints.Select(x => x.ToString()).ToArray());
jest równa:
var result = string.Join(",", ints);
EDYCJA :
Widzę, że kilka rozwiązań reklamuje użycie StringBuilder. Ktoś narzeka, że metoda Join powinna przyjmować argument IEnumerable.
Zawiodę Cię :) String.Join wymaga tablicy z jednego powodu - wydajności. Metoda Join musi znać rozmiar danych, aby skutecznie przydzielić niezbędną ilość pamięci.
Oto fragment wewnętrznej implementacji metody 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]);
}
}
Jestem zbyt leniwy, aby porównać wydajność sugerowanych metod. Ale coś mi mówi, że Join wygra :)
using System.Linq;
jest wymagane.
Chociaż w OP określono .NET 3.5, osoby, które chcą to zrobić w .NET 2.0 z C # 2, mogą to zrobić:
string.Join(",", Array.ConvertAll<int, String>(ints, Convert.ToString));
Uważam, że istnieje wiele innych przypadków, w których użycie funkcji Convert.xxx jest lepszą alternatywą dla lambdy, chociaż w języku C # 3 lambda może pomóc w wnioskowaniu o typie.
Dość kompaktowa wersja C # 3, która współpracuje z .NET 2.0 to:
string.Join(",", Array.ConvertAll(ints, item => item.ToString()))
Jedną z mieszanin tych dwóch podejść byłoby napisanie metody rozszerzenia w IEnumerable <T>, która używała StringBuilder. Oto przykład z różnymi przeciążeniami w zależności od tego, czy chcesz określić transformację, czy po prostu polegać na zwykłym ToString. Nazwałem metodę „JoinStrings” zamiast „Join”, aby uniknąć pomyłki z innym typem Join. Może ktoś wymyśli lepszą nazwę :)
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());
Musimy przekonwertować każdy z elementów na a, String
zanim będziemy mogli je połączyć, więc sensowne jest użycie Select
i wyrażenie lambda. Jest to równoważne map
w niektórych innych językach. Następnie musimy przekonwertować wynikowy zbiór ciągów z powrotem na tablicę, ponieważString.Join
akceptuje tylko tablicę ciągów.
ToArray()
Jest nieco brzydki myślę. String.Join
powinien naprawdę zaakceptować IEnumerable<String>
, nie ma powodu, aby ograniczać go tylko do tablic. Dzieje się tak prawdopodobnie dlatego, że Join
pochodzi z czasów przed typami generycznymi, kiedy tablice były jedynym dostępnym rodzajem kolekcji.
Jeśli twoja tablica liczb całkowitych może być duża, uzyskasz lepszą wydajność, używając StringBuilder. Na przykład:
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();
Edycja: Kiedy to opublikowałem, miałem błędne wrażenie, że „StringBuilder.Append (int value)” wewnętrznie zdołał dołączyć ciąg znaków reprezentujący wartość całkowitą bez tworzenia obiektu ciągu. To jest złe: sprawdzanie metody za pomocą Reflectora pokazuje, że po prostu dołącza value.ToString ().
Dlatego jedyną potencjalną różnicą w wydajności jest to, że ta technika pozwala uniknąć tworzenia jednej tablicy i nieco wcześniej zwalnia ciągi do wyrzucania elementów bezużytecznych. W praktyce nie da to żadnej wymiernej różnicy, więc głosowałem za tym lepszym rozwiązaniem .
Pytanie dotyczy „najłatwiejszego sposobu przekształcenia ich w pojedynczy ciąg, w którym liczby są oddzielone znakiem”.
Najłatwiej jest:
int[] numbers = new int[] { 2,3,6,7 };
string number_string = string.Join(",", numbers);
// do whatever you want with your exciting new number string
EDYCJA: To działa tylko w .NET 4.0+, brakowało mi wymagania .NET 3.5, gdy po raz pierwszy przeczytałem pytanie.
Zgadzam się z wyrażeniem lambda dotyczącym czytelności i łatwości konserwacji, ale nie zawsze będzie to najlepsza opcja. Wadą stosowania zarówno podejścia IEnumerable / ToArray, jak i StringBuilder jest to, że muszą one dynamicznie rozwijać listę elementów lub znaków, ponieważ nie wiedzą, ile miejsca będzie potrzebne na końcowy ciąg.
W rzadkich przypadkach, w których szybkość jest ważniejsza niż zwięzłość, bardziej efektywne są poniższe czynności.
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);
W .NET 4.0 łączenie ciągów ma przeciążenie dla params object[]
, więc jest tak proste, jak:
int[] ids = new int[] { 1, 2, 3 };
string.Join(",", ids);
przykład
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));
W .NET 2.0 jest to trochę trudniejsze, ponieważ nie ma takiego przeciążenia. Potrzebujesz więc własnej ogólnej metody:
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;
}
W .NET 3.5 można używać metod rozszerzających:
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;
}
}
Możesz więc użyć metody rozszerzenia JoinArray.
int[] ids = new int[] { 1, 2, 3 };
string strIdList = ids.JoinArray(",");
Możesz również użyć tej metody rozszerzenia w .NET 2.0, jeśli dodasz ExtensionAttribute do swojego kodu:
// 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 {}
}
Możesz to zrobić
ints.ToString(",")
ints.ToString("|")
ints.ToString(":")
Sprawdzić
Separator Delimited ToString dla Array, List, Dictionary, Generic IEnumerable