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

Pos*_*Guy 6 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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

是的,有更多的"优雅"的方式与LINQ这样做,但我想这样做manually..the老办法,现在只是我自己的理解.

另外,困扰我的是:

list.AddRange(str.Split(';').Select(Int32.Parse));
Run Code Online (Sandbox Code Playgroud)

是我不知道的:

  1. 如何在那里推送TryParse.
  2. 如果str.Split(';').Select(Int32.Parse)因为某种原因失败了怎么办......那么这个AddRange所处的方法会爆炸,除非我在整个事情中添加一个try/catch,如果我没有正确处理它,我就搞砸了.

cod*_*zen 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>());
Run Code Online (Sandbox Code Playgroud)

发问者说明:

除了在循环中拆分并进行转换然后添加到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?);
    } 
}
Run Code Online (Sandbox Code Playgroud)

非平行:00:00:07.0719911

平行:00:00:04.5933906

  • @coffeeaddict,我完全不同意你在优化方面的立场,因为我相信大多数其他开发人员会这样做.当然,性能可能就是一切,但是猜测性能受到影响的地方不应该预先做好,而且你总是会弄错,最后会得到更加清晰的不透明代码.设计得很好,代码清晰,然后只在问题出现时进行优化. (3认同)
  • @coffeeaddict:抱歉,但我不同意.即使在这种规模下,代码可读性和可维护性也要超过毫秒,特别是当它的扩展成本太低时. (3认同)
  • 如果你最大的性能问题是字符串拆分功能,那么你是一个非常幸运的程序员.我不相信LINQ在foreach循环上有任何显着的开销,对于天真的程序员来说,当他们看不到嵌套时,他们很容易忘记他们的大O复杂性. (2认同)

Dav*_*vid 5

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

foreach (string s in str.Split(';'))
{
    list.Add( Int32.Parse(s));
}
Run Code Online (Sandbox Code Playgroud)