2008-09-28 24 views
87

Tôi có một mảng các số nguyên:Làm cách nào để nối int [] vào chuỗi ký tự được phân cách bằng .NET?

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

cách dễ nhất chuyển đổi chúng thành một chuỗi duy nhất, nơi những con số được ngăn cách bởi một nhân vật là gì (như: "2,3,6,7")?

Tôi đang ở trong C# và .NET 3.5.

+2

SO rocks! Tôi có 3 câu trả lời tuyệt vời này trong vòng 10 phút vào Chủ Nhật! – Riri

+3

Kể từ '.NET 4.0', có các phương thức lấy một mảng các đối tượng và một IEnumerable để bạn có thể thực hiện' string.join (",", number) '. Tôi biết câu hỏi chỉ định NET 3.5. Vì vậy, tôi đã không làm cho câu trả lời này, nhưng nó đi lên trong tìm kiếm mà không chỉ định một phiên bản và biết nó có thể trong 4,0 có thể giúp một ai đó. –

Trả lời

144
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:

tôi thấy một số giải pháp quảng cáo sử dụng StringBuilder. Một người nào đó khiếu nại rằng phương pháp tham gia nên có một đối số IEnumerable.

Tôi sẽ làm bạn thất vọng :) String.Join yêu cầu mảng vì một lý do duy nhất - hiệu suất. Tham gia phương thức cần phải biết kích thước của dữ liệu để có hiệu quả preallocate lượng bộ nhớ cần thiết.

Đây là một phần của việc thực hiện nội bộ của phương pháp 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]); 
    } 
} 

tôi quá lười biếng để so sánh hiệu suất của phương pháp đề nghị. Nhưng một cái gì đó nói với tôi rằng gia sẽ giành chiến thắng :)

+0

Điều này có lẽ là đặt cược tốt nhất bằng cách sử dụng các phương pháp mở rộng lõi .NET, nhưng tôi thực sự muốn string.Join() sẽ chấp nhận một IEnumerable để tránh chuyển đổi ToArray(). – spoulson

+0

Không có gì ngăn cản ai đó quá tải chuỗi. Cũng cần có một IEnumerable. ;) –

+1

Đây có lẽ cũng là giải pháp dễ nhất và không chỉ là nhanh nhất. –

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

Chúng ta phải chuyển đổi mỗi mục để một String trước khi chúng tôi có thể tham gia cùng họ, vì vậy nó làm cho cảm giác sử dụng Select và một biểu thức lambda. Điều này tương đương với map bằng một số ngôn ngữ khác. Sau đó, chúng ta phải chuyển đổi tập hợp chuỗi kết quả thành một mảng, vì String.Join chỉ chấp nhận một mảng chuỗi.

ToArray() hơi xấu xí. String.Join thực sự nên chấp nhận IEnumerable<String>, không có lý do để hạn chế nó chỉ mảng. Điều này có lẽ chỉ vì Join là từ trước khi generics, khi mảng là loại duy nhất của bộ sưu tập đánh máy có sẵn.

5

Nếu mảng số nguyên của bạn có thể lớn, bạn sẽ nhận được hiệu suất tốt hơn bằng cách sử dụng một StringBuilder. Ví dụ .:

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

Chỉnh sửa: Khi tôi đăng này tôi đã theo ấn tượng sai lầm rằng "StringBuilder.Append (int value)" trong nội bộ quản lý để nối thêm chuỗi đại diện của các giá trị số nguyên mà không cần tạo một đối tượng chuỗi. Điều này là sai: kiểm tra phương pháp với Reflector cho thấy rằng nó chỉ đơn giản gắn thêm value.ToString().

Do đó, sự khác biệt hiệu suất tiềm năng duy nhất là kỹ thuật này tránh tạo một mảng và giải phóng các chuỗi để thu thập rác sớm hơn một chút. Trong thực tế, điều này sẽ không tạo ra bất kỳ sự khác biệt có thể đo lường nào, vì vậy tôi đã upvoted this better solution.

+0

Bạn đã đo nó nhanh hơn chưa? String.Join cũng sử dụng StringBuilder. – JacquesB

+0

Có, nhưng trước tiên bạn cần phải chuyển đổi toàn bộ điều thành một mảng, đó là xa lý tưởng. Đặc biệt, nó có nghĩa là bạn cần phải có tất cả các chuỗi được chuyển đổi trong bộ nhớ cùng một lúc, * trước * bạn bắt đầu xây dựng chuỗi kết quả. –

+0

Chuỗi OTOH.Jinin tính toán trước kích thước của bộ đệm StringBuilder để tránh bị thay đổi kích thước. Vì vậy, nó có thể nhanh hơn ngay cả khi nó đòi hỏi nhiều bộ nhớ hơn. – JacquesB

10

Một hỗn hợp của hai cách tiếp cận sẽ là viết một phương pháp mở rộng trên IEnumerable < T> đã sử dụng một StringBuilder. Dưới đây là một ví dụ, với quá tải khác nhau tùy thuộc vào việc bạn muốn chỉ định chuyển đổi hoặc chỉ dựa vào ToString đơn giản. Tôi đã đặt tên cho phương thức "JoinStrings" thay vì "Tham gia" để tránh nhầm lẫn với loại Tham gia khác.Có lẽ ai đó có thể đưa ra một tên tốt hơn :)

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

Giải pháp tốt! Bạn không cần tham số chiếu mặc dù, bạn chỉ có thể viết x.Select (i => i.ToString ("X")). JoinStrings (";") đó là thành ngữ hơn. – JacquesB

+0

Vâng, tôi đã nghĩ về điều đó sau đó. Thỉnh thoảng thật tuyệt khi có thể chỉ định tất cả trong một lần, nhưng chắc chắn thanh lịch hơn để tách hoạt động :) –

2

Tôi đồng ý với biểu thức lambda để dễ đọc và bảo trì, nhưng nó không phải lúc nào cũng là lựa chọn tốt nhất. Nhược điểm của việc sử dụng cả phương pháp tiếp cận IEnumerable/ToArray và StringBuilder là chúng phải tự động phát triển một danh sách, một trong các mục hoặc ký tự, vì chúng không biết bao nhiêu khoảng trống sẽ cần thiết cho chuỗi cuối cùng.

Nếu trường hợp hiếm hoi trong đó tốc độ quan trọng hơn mức độ phù hợp, sau đây là hiệu quả hơn.

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

Mặc dù OP định .NET 3.5, những người muốn làm điều này trong .NET 2.0 với C# 2 có thể làm điều này:

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

Tôi thấy có một số trường hợp khác mà việc sử dụng các chức năng Convert.xxx là một lựa chọn thay thế cho một lambda, mặc dù trong C# 3 lambda có thể giúp loại-inferencing.

Một khá nhỏ gọn C# 3 phiên bản mà làm việc với .NET 2.0 là thế này:

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

Và điều này hoạt động trong cửa sổ Xem trong khi gỡ lỗi. –

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

Tôi cũng nghĩ là có một cách đơn giản hơn. Không biết về hiệu suất, bất cứ ai có bất kỳ ý tưởng (lý thuyết)?

+0

Giải pháp này sẽ cung cấp cho bạn ", 1,2,3,4,5". – user347805

+0

Cảm ơn, tôi đã thêm 'Chuỗi con (1)' để sửa lỗi đó (từ bộ nhớ). – void

5

Câu hỏi đặt ra là "cách dễ dàng nhất để chuyển đổi chúng thành một chuỗi duy nhất trong đó số được phân tách bằng ký tự".

Cách đơn giản nhất là:

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: Đây chỉ hoạt động trong .NET 4.0 trở lên, tôi đã bỏ lỡ các yêu cầu .NET 3.5 lần đầu tiên tôi đọc câu hỏi.

+0

Đây không phải là hợp lệ như chuỗi. Phương pháp này chỉ mất một chuỗi các chuỗi. Có một cái nhìn ở đây http://msdn.microsoft.com/en-us/library/tk0xe5h0.aspx – ppolyzos

+1

Nó là một phương pháp quá tải: http://msdn.microsoft.com/en-us/library/dd988350 Tôi chỉ sao chép mã tôi đã viết vào một ứng dụng giao diện điều khiển mới, thêm một Console.WriteLine và đây là đầu ra: 2,3,6,7 – WebMasterP

+1

Tôi nghĩ rằng điều này chỉ có sẵn trong .net 4 –

1

Trong .NET 4.0, chuỗi tham gia có tình trạng quá tải cho params object[], do đó, nó đơn giản như:

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

dụ

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

Trong .NET 2.0, nó khó khăn hơn một chút nhỏ , vì không có quá tải. Vì vậy, bạn cần phương pháp của riêng chung:

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

Trong .NET 3.5, bạn có thể sử dụng phương pháp khuyến nông:

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

} 

Vì vậy, bạn có thể sử dụng phần mở rộng JoinArray-method.

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

Bạn cũng có thể sử dụng phương pháp mở rộng đó trong .NET 2.0, nếu bạn thêm ExtensionAttribute vào mã của mình:

// 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 {} 
} 
Các vấn đề liên quan