将分隔的字符串推入List <int> </int>

时间:2010-06-29 01:23:31

标签: c# string parsing

如果我有以下字符串:

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

这是我计划在每次需要将分隔的字符串列表转换为List时使用的新字符串实用程序方法

所以如果出现问题,我会将一个空列表返回给调用者。好坏?这样做很常见吗?

是的,使用LINQ有更多“优雅”的方法可以做到这一点,但我想手动完成它...现在只是为了我自己的理解。

另外,令我困扰的是:

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

是我不知道的:

  1. 如何在那里推送TryParse。
  2. 如果str.Split(';').Select(Int32.Parse)因任何原因失败了怎么办...那么这个AddRange所处的方法会爆炸,除非我在这整个过程中添加一个try / catch,我搞砸了我没有妥善处理。

5 个答案:

答案 0 :(得分: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>());

提问者注意:

  

除了在循环中拆分并进行转换然后添加到List

之外,我不知道这里有什么好方法

一般来说,这是为什么LINQ被引入C#的一个主要原因 - 通过实现循环来消除处理值序列的需要,而只是声明你想要转换序列。如果你发现自己在想“除了循环之外我不知道如何做到这一点” - 现在是时候研究一个能为你完成工作的LINQ结构。

效果更新:

LINQ的性能问题如下。虽然在评论中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

答案 1 :(得分:5)

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

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

答案 2 :(得分:3)

List<int> list = (from numString in "123;3344;4334;12".Split(';') 
                  select int.Parse(numString)).ToList();

答案 3 :(得分: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可能已将ForEach添加到Enumerable<T>,因此可能不需要ToList(无法测试)。

答案 4 :(得分:-1)

我认为这是最简单的

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