2010-06-29 46 views
6

如果我有例如以下字符串:肖夫分隔字符串到列表<int>

「123; 3344; 4334; 12」

和我在一個通用的List<int>希望這些數字,我想我在這裏不知道一個好的方法,除了分割循環並進行轉換,然後通過每次迭代添加到List<int>。有沒有人有其他方式去解決這個問題?

已更新。這是我想出來的。我想以舊式的方式來做到這一點,而不是LINQ,因爲我試圖通過字符串,數組,列表以及操作和轉換來獲得更好的效果。

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

這是一個新的字符串的工具方法我打算使用每當我需要轉換分隔字符串列表列出

如果事情失敗,所以我返回一個空列表返回給調用者。好壞?這樣做很常見嗎?

是的,有更多的「優雅」的方式來做到這一點與LINQ,但我想手動做...舊的方式現在只是爲了我自己的理解。

而且,讓我困擾這一點:

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

的是,我不知道:

  1. 如何在推的TryParse而是存在。
  2. 如果str.Split(';').Select(Int32.Parse)只是由於某種原因失敗了......那麼這個AddRange所在的方法將會炸燬,除非我在這整個事情上添加一個try/catch,否則我會搞砸妥善處理。
+0

使用的TryParse這裏是一個嚴重的錯誤:http://en.wikipedia.org/wiki/GIGO – 2010-06-29 05:09:12

回答

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,你讀的稱號!我會建議使用TryParse而不是Parse。 – 2010-06-29 01:31:08

+0

如果你可以做的話,我就可以做清單 list =「123; 3344; 4334; 12」.Split(「;」);我知道你可以用一個數組:string [] list =「123; 3344; 4334; 12」.Split(「;」); – PositiveGuy 2010-06-29 01:35:12

+1

@coffee,no。你不能隱式地從一個字符串數組轉換成一個'List '。另外,它應該是'Split'(';')'。請注意單引號,因爲它是一個字符文字。 – 2010-06-29 01:35:59

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

發問指出:

我不知道這裏除了在循環分裂,做一個轉換的好方法,然後添加到列表

一般來說,這是LINQ被引入C#中的一個重要原因移動需要通過實現循環來處理值序列,而是隻聲明你想要轉換序列的意圖。如果你發現自己在思考「我不知道如何做到這一點,除了一個循環」 - 現在是時候研究一下LINQ構造,它將爲你做好工作。

性能更新:

LINQ的性能已經低於quesioned。在評論中,由於我們獲得了可讀性,可維護性和可組合性的好處,因此LINQ的速度變慢的思想得到了捍衛,但還有另一個方面給LINQ帶來了簡單的性能優勢:並行性。以下是僅添加一個擴展方法調用的示例,AsParallel()將性能提高一倍。這是一個很好的例子,在這種情況下,橫向擴展甚至不需要非常小心地進行測量即可輕鬆實現微型優化。注意我沒有聲稱微型優化不是必需的,但是通過我們在這個絕對級別上可用的工具,需求變得微乎其微。

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

非平行:00:00:07.0719911

並行:00:00:04.5933906

+0

是的,我想知道性能與循環中的標準拆分雖然 – PositiveGuy 2010-06-29 01:40:43

+0

@coffeeaddict:它幾乎總是可以忽略的,它只應該考慮更改,如果它被測量並發現這是一個很好的近期比較:http://jerrytech.blogspot.com/2010/02/revisiting-c-loop-performance.html – codekaizen 2010-06-29 01:45:38

+0

我不知道我總是在這裏你可以過度使用LINQ,它可以開始是一個性能豬。不是說你錯了...是的 – PositiveGuy 2010-06-29 01:53:31

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

我聽說過.NET 4.0可能已經添加到ForEachEnumerable<T>,所以ToList在那裏可能是不必要的(不能測試)。

+0

在ToList之後,你有*一個整數列表。 ForEach是不需要的。 – 2010-06-29 01:39:03

+0

@Matthew Flaschen,同意。我最初的(也是匆匆忙忙的)最初的想法是列表可能不是原創的,並且內容可能需要保留。即將結果附加到現有的列表而無需替換。 – 2010-06-29 01:41:42

-1

我覺得這是最簡單的

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

-1:這絕對不行,因爲你不能將一個字符串轉換爲一個整數。你只能解析它(使用'int.Parse()'或'int.TryParse()')。 – Oliver 2013-07-23 05:53:44