如果我有以下字符串:
“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));
是我不知道的:
str.Split(';').Select(Int32.Parse)
因任何原因失败了怎么办...那么这个AddRange所处的方法会爆炸,除非我在这整个过程中添加一个try / catch,我搞砸了我没有妥善处理。答案 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>();