2010-06-29 23 views
6

Nếu tôi có ví dụ chuỗi sau:Xô một chuỗi phân định vào một danh sách <int>

"123; 3344; 4334; 12"

và tôi muốn những con số này trong một generic List<int>, tôi đoán tôi không biết một cách tốt ở đây ngoài việc chia nhỏ vòng lặp và thực hiện chuyển đổi rồi thêm vào một số List<int> thông qua mỗi lần lặp. Có ai có cách khác để đi về điều này?

Đã cập nhật. Đây là những gì tôi nghĩ ra. Tôi muốn làm điều này theo cách thời trang cũ, không phải với LINQ bởi vì tôi đang cố gắng để có được tốt hơn với chỉ chuỗi, mảng, danh sách và thao tác và chuyển đổi nói chung.

public List<int> StringToList(string stringToSplit, char splitDelimiter) 
{ 
    List<int> list = new List<int>(); 

    if (string.IsNullOrEmpty(stringToSplit)) 
     return list; 

    string[] values = stringToSplit.Split(splitDelimiter); 

    if (values.Length <= 1) 
     return list; 

    foreach (string s in values) 
    { 
     int i; 
     if (Int32.TryParse(s, out i)) 
      list.Add(i); 
    } 

    return list; 
} 

Đây là một phương pháp chuỗi tiện ích mới, tôi có kế hoạch về việc sử dụng bất cứ khi nào tôi cần phải chuyển đổi một danh sách chuỗi phân vào danh sách

Vì vậy, tôi trả lại một danh sách trống lại cho người gọi nếu có điều gì thất bại. Tốt xấu? là nó khá phổ biến để làm điều này?

Có, có nhiều cách "thanh lịch" hơn để làm điều này với LINQ nhưng tôi muốn làm điều đó theo cách thủ công .. cách cũ cho bây giờ chỉ vì sự hiểu biết của riêng tôi.

Ngoài ra, những gì tôi làm phiền về điều này:

list.AddRange(str.Split(';').Select(Int32.Parse)); 

là tôi không có ý tưởng:

  1. Làm thế nào để xô trong một TryParse có để thay thế.
  2. Điều gì xảy ra nếu str.Split(';').Select(Int32.Parse) không thành công vì lý do gì ... thì phương pháp mà AddRange này đang ở sẽ nổ tung và trừ khi tôi thêm thử/nắm bắt toàn bộ vấn đề này xử lý nó đúng cách.
+0

Sử dụng TryParse đây là một sai lầm nghiêm trọng: http://en.wikipedia.org/wiki/GIGO –

Trả lời

5
string str = "123;3344;4334;12"; 
List<int> list = new List<int>(); 

foreach (string s in str.Split(';')) 
{ 
    list.Add(Int32.Parse(s)); 
} 
+1

+1, bạn đọc tiêu đề! Tôi sẽ đề nghị sử dụng TryParse thay vì Parse. –

+0

Tôi bị thương nếu bạn chỉ có thể làm Danh sách list = "123; 3344; 4334; 12" .Split (";"); Tôi biết bạn có thể với một mảng: string [] list = "123; 3344; 4334; 12" .Split (";"); – PositiveGuy

+1

@coffee, no. Bạn không thể chuyển đổi hoàn toàn từ một chuỗi các chuỗi thành một 'Danh sách '. Ngoài ra, nó phải là 'Split (';')'. Lưu ý các trích dẫn duy nhất, bởi vì nó là một ký tự chữ. –

3
List<int> list = (from numString in "123;3344;4334;12".Split(';') 
        select int.Parse(numString)).ToList(); 
6
static int? ToInt32OrNull(string s) 
{ 
    int value; 
    return (Int32.TryParse(s, out value)) ? value : default(int?);  
} 
// ... 
var str = "123;3344;4334;12"; 
var list = new List<int>(); 
list.AddRange(str.Split(';') 
       .Select(ToInt32OrNull) 
       .Where(i => i != null) 
       .Cast<int>()); 

Người hỏi lưu ý:

Tôi không biết một cách tốt ở đây không phải là để phân chia trong một vòng lặp và làm một chuyển đổi sau đó thêm vào một danh sách

Nói chung, đây là lý do chính khiến LINQ được đưa vào C# - để lại di chuyển sự cần thiết phải làm việc với chuỗi các giá trị bằng cách thực hiện các vòng lặp, và thay vào đó chỉ cần khai báo ý định của bạn để biến đổi chuỗi. Nếu bạn từng thấy mình suy nghĩ "Tôi không biết làm thế nào để làm điều này ngoại trừ với một vòng lặp" - đó là thời gian để nhìn vào một cấu trúc LINQ mà sẽ làm công việc cho bạn.

Hiệu suất Cập nhật:

Hiệu suất của LINQ đã được quesioned dưới đây. Trong khi trong các ý kiến, ý tưởng của LINQ bị chậm lại được bảo vệ vì chúng ta thu được lợi ích của khả năng đọc, bảo trì và tính tương hợp, có một khía cạnh khác mang lại cho LINQ một lợi thế hiệu suất dễ dàng: song song. Dưới đây là ví dụ khi chỉ thêm một cuộc gọi phương thức tiện ích mở rộng, AsParallel() tăng gấp đôi hiệu suất. Đây là một ví dụ tuyệt vời về nơi mà quy mô-out nhịp đập tối ưu hóa vi mô mà không cần phải đo lường rất cẩn thận.Lưu ý Tôi không tuyên bố rằng tối ưu hóa vi mô là không bao giờ cần thiết, nhưng với các công cụ chúng tôi đã có sẵn ở cấp độ này, sự cần thiết trở nên biến mất nhỏ.

class Program 
{ 
    private const int ElementCount = 10000000; 

    static void Main(string[] args) 
    { 
     var str = generateString(); 
     var stopwatch = new Stopwatch(); 

     var list1 = new List<int>(ElementCount); 
     var list2 = new List<int>(ElementCount); 

     var split = str.Split(';'); 

     stopwatch.Start(); 
     list1.AddRange(split 
          .Select(ToInt32OrNull) 
          .Where(i => i != null) 
          .Cast<int>()); 
     stopwatch.Stop(); 

     TimeSpan nonParallel = stopwatch.Elapsed; 

     stopwatch.Restart(); 

     list2.AddRange(split 
          .AsParallel() 
          .Select(ToInt32OrNull) 
          .Where(i => i != null) 
          .Cast<int>()); 

     stopwatch.Stop(); 

     TimeSpan parallel = stopwatch.Elapsed; 

     Debug.WriteLine("Non-parallel: {0}", nonParallel); 
     Debug.WriteLine("Parallel: {0}", parallel); 
    } 

    private static String generateString() 
    { 
     var builder = new StringBuilder(1048576); 
     var rnd = new Random(); 

     for (int i = 0; i < ElementCount; i++) 
     { 
      builder.Append(rnd.Next(99999)); 
      builder.Append(';'); 
     } 

     builder.Length--; 

     return builder.ToString(); 
    } 

    static int? ToInt32OrNull(string s) 
    { 
     int value; 
     return (Int32.TryParse(s, out value)) ? value : default(int?); 
    } 
} 

không song song: 00: 00: 07,0719911

Parallel: 00: 00: 04,5933906

+0

yea Tôi tự hỏi về hiệu suất so với phân chia chuẩn trong một vòng lặp mặc dù – PositiveGuy

+0

@coffeeaddict: Nó hầu như luôn không thể bỏ qua, và nó chỉ nên được xem xét thay đổi nếu nó được đo lường và tìm thấy Đây là một sự so sánh gần đây, tốt: http://jerrytech.blogspot.com/2010/02/revisiting-c-loop-performance.html – codekaizen

+0

Tôi không biết tôi luôn ở đây bạn có thể lạm dụng LINQ trong đó Nó không thể nói rằng bạn đang sai ... yea – PositiveGuy

1
string myString = "123;3344;4334;12"; 
var ints = new List<int>(); 
(from s in myString.Split(';') 
select int.Parse()).ToList().ForEach(i=>ints.Add(i)); 

Tôi đã nghe Net 4.0 có thể đã thêm ForEach để Enumerable<T>, vì vậy, ToList có thể không cần thiết ở đó (không thể kiểm tra).

+0

Sau 'ToList', bạn * có * một danh sách các int. 'ForEach' không cần thiết. –

+0

@Matthew Flaschen, đã đồng ý. Ý tưởng ban đầu của tôi (và thừa nhận vội vã) ban đầu là danh sách có thể không phải là bản gốc và các nội dung có thể cần được bảo tồn. tức là nối kết quả vào danh sách hiện có mà không cần thay thế. –

-1

Tôi nghĩ rằng đây là đơn giản nhất

var str = "123;3344;4334;12"; 
    var list = str.Split(';').ToList().Cast<int>(); 
+0

-1: Điều này không bao giờ hoạt động, khiến bạn không thể truyền chuỗi thành số nguyên. Bạn chỉ có thể phân tích cú pháp nó (sử dụng 'int.Parse()' hoặc 'int.TryParse()'). – Oliver

Các vấn đề liên quan