Bagaimana cara menggabungkan int [] ke string yang dipisahkan karakter di .NET?

101

Saya memiliki array bilangan bulat:

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

Apa cara termudah untuk mengubahnya menjadi string tunggal di mana angka-angkanya dipisahkan oleh karakter (seperti "2,3,6,7":)?

Saya menggunakan C # dan .NET 3.5.

Riri
sumber
3
BANGET! Saya mendapat 3 jawaban luar biasa ini dalam 10 menit pada hari Minggu!
Riri
4
Seperti .NET 4.0ada metode yang mengambil array objek dan IEnumerable sehingga Anda bisa melakukannya string.join(",", number). Saya tahu pertanyaannya menentukan .NET 3.5 jadi saya tidak membuat ini jawaban, tetapi muncul dalam pencarian yang tidak menentukan versi dan mengetahui itu mungkin di 4.0 dapat membantu seseorang.
Jason Goemaat

Jawaban:

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"

EDIT : Pada (setidaknya) .NET 4.5,

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

setara dengan:

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

EDIT :

Saya melihat beberapa solusi mengiklankan penggunaan StringBuilder. Seseorang mengeluh bahwa metode Gabung harus mengambil argumen IEnumerable.

Saya akan mengecewakan Anda :) String.Join membutuhkan array karena satu alasan - kinerja. Metode gabungan perlu mengetahui ukuran data untuk secara efektif mengalokasikan jumlah memori yang diperlukan.

Berikut adalah bagian dari implementasi internal metode 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]);
    }
}

Saya terlalu malas untuk membandingkan kinerja metode yang disarankan. Tapi ada yang memberitahuku bahwa Join akan menang :)

aku
sumber
Ini mungkin taruhan terbaik menggunakan metode ekstensi .NET inti, tetapi saya benar-benar berharap string.Join () akan menerima <string> IEnumerable untuk menghindari konversi ToArray ().
spoulson
Tidak ada yang mencegah seseorang untuk membebani string secara berlebihan. Bergabunglah untuk mengambil IEnumerable, juga. ;)
Robert P
1
Ini mungkin juga solusi termudah, dan bukan hanya yang tercepat.
Dave Van den Eynde
9
.NET 4 menyediakan kelebihan String.Join yang menerima IEnumerable sebagai parameter. msdn.microsoft.com/en-us/library/dd783876.aspx
Ryan Kohn
using System.Linq;diperlukan.
Gayan Weerakutti
32

Meskipun OP menentukan .NET 3.5, orang yang ingin melakukan ini di .NET 2.0 dengan C # 2 dapat melakukan ini:

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

Saya menemukan ada sejumlah kasus lain di mana penggunaan fungsi Convert.xxx adalah alternatif yang lebih rapi untuk lambda, meskipun di C # 3 lambda mungkin membantu inferensi tipe.

Versi C # 3 yang cukup ringkas yang bekerja dengan .NET 2.0 adalah ini:

string.Join(",", Array.ConvertAll(ints, item => item.ToString()))
Will Dean
sumber
11

Salah satu campuran dari dua pendekatan tersebut adalah menulis metode ekstensi pada IEnumerable <T> yang menggunakan StringBuilder. Berikut adalah contoh, dengan kelebihan beban yang berbeda bergantung pada apakah Anda ingin menentukan transformasi atau hanya mengandalkan ToString biasa. Saya telah menamai metode "JoinStrings" daripada "Gabung" untuk menghindari kebingungan dengan jenis Gabung lainnya. Mungkin seseorang bisa mendapatkan nama yang lebih baik :)

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"), ","));
    }
}
Jon Skeet
sumber
Solusi bagus! Anda tidak memerlukan parameter proyeksi, Anda cukup menulis x.Select (i => i.ToString ("X")). JoinStrings (";") yang lebih idiomatis.
JacquesB
Ya, saya memikirkannya setelah itu. Kadang-kadang menyenangkan dapat menentukan semuanya sekaligus, tetapi jelas lebih elegan untuk membagi operasi :)
Jon Skeet
8
String.Join(";", number.Select(item => item.ToString()).ToArray());

Kita harus mengonversi setiap item menjadi a Stringsebelum kita dapat menggabungkannya, jadi masuk akal untuk menggunakan Selectdan ekspresi lambda. Ini sama dengan mapdi beberapa bahasa lain. Kemudian kita harus mengubah kumpulan string yang dihasilkan kembali menjadi array, karena String.Joinhanya menerima array string.

The ToArray()sedikit jelek saya pikir. String.Joinharus benar-benar menerima IEnumerable<String>, tidak ada alasan untuk membatasinya hanya pada array. Ini mungkin hanya karena Joindari sebelum generik, ketika array adalah satu-satunya jenis koleksi yang diketik yang tersedia.

JacquesB
sumber
5

Jika array bilangan bulat Anda mungkin besar, Anda akan mendapatkan kinerja yang lebih baik menggunakan StringBuilder. Misalnya:

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

Sunting: Ketika saya memposting ini saya berada di bawah kesan yang salah bahwa "StringBuilder.Append (int value)" secara internal berhasil menambahkan representasi string dari nilai integer tanpa membuat objek string. Ini salah: memeriksa metode dengan Reflector menunjukkan bahwa itu hanya menambahkan value.ToString ().

Oleh karena itu, satu-satunya perbedaan performa potensial adalah bahwa teknik ini menghindari satu pembuatan array, dan membebaskan string untuk pengumpulan sampah sedikit lebih cepat. Dalam praktiknya, ini tidak akan membuat perbedaan terukur, jadi saya telah memberikan suara positif untuk solusi yang lebih baik ini .

Joe
sumber
Sudahkah Anda mengukurnya menjadi lebih cepat? String.Join juga menggunakan StringBuilder.
JacquesB
Ya, tetapi Anda harus terlebih dahulu mengonversi semuanya menjadi array, yang jauh dari ideal. Secara khusus, ini berarti bahwa Anda harus memiliki semua string yang dikonversi dalam memori pada saat yang sama, sebelum Anda mulai membuat string yang dihasilkan.
Jon Skeet
OTOH String.Join menghitung sebelumnya ukuran buffer StringBuilder sehingga ukuran tidak diubah. Jadi mungkin lebih cepat meski membutuhkan lebih banyak memori.
JacquesB
5

Pertanyaannya adalah untuk "cara termudah untuk mengubahnya menjadi string tunggal di mana nomor tersebut dipisahkan oleh karakter".

Cara termudah adalah:

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

EDIT: Ini hanya berfungsi di .NET 4.0+, saya melewatkan persyaratan .NET 3.5 saat pertama kali saya membaca pertanyaan.

WebMasterP
sumber
Ini tidak valid karena metode string.Join hanya membutuhkan array string. Lihat di sini msdn.microsoft.com/en-us/library/tk0xe5h0.aspx
ppolyzos
1
Ini adalah metode kelebihan beban: msdn.microsoft.com/en-us/library/dd988350 Saya baru saja menyalin kode yang saya tulis ke dalam aplikasi konsol baru, menambahkan Console.WriteLine dan ini adalah output: 2,3,6,7
WebMasterP
1
Saya pikir ini hanya tersedia dalam .net 4
Govind Malviya
Membutuhkan larik objek (atau larik string), bukan larik int. Akan memberikan kesalahan "panggilan ambigu".
LarryBud
2

Saya setuju dengan ekspresi lambda untuk keterbacaan dan pemeliharaan, tetapi itu tidak selalu menjadi pilihan terbaik. Kelemahan untuk menggunakan pendekatan IEnumerable / ToArray dan StringBuilder adalah mereka harus mengembangkan daftar secara dinamis, baik item atau karakter, karena mereka tidak tahu berapa banyak ruang yang akan dibutuhkan untuk string terakhir.

Jika kasus yang jarang terjadi di mana kecepatan lebih penting daripada keringkasan, berikut ini lebih efisien.

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);
DocMax
sumber
2
ints.Aggregate("", ( str, n ) => str +","+ n ).Substring(1);

Saya juga berpikir ada cara yang lebih sederhana. Tidak tahu tentang kinerja, ada yang punya ide (teoritis)?

kosong
sumber
Solusi ini akan memberi Anda ", 1,2,3,4,5".
Sarin
Terima kasih, saya telah menambahkan Substring(1)untuk memperbaikinya (itu dari memori).
batal
2

Di .NET 4.0, gabungan string memiliki kelebihan beban params object[], jadi sesederhana:

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

contoh

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

Di .NET 2.0, ini sedikit lebih sulit, karena tidak ada kelebihan beban seperti itu. Jadi, Anda memerlukan metode umum Anda sendiri:

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

Di .NET 3.5, Anda dapat menggunakan metode ekstensi:

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

}

Jadi Anda dapat menggunakan metode ekstensi JoinArray.

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

Anda juga dapat menggunakan metode ekstensi itu di .NET 2.0, jika Anda menambahkan ExtensionAttribute ke kode Anda:

// 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 {}
}
Stefan Steiger
sumber