我有一个foreach循环,我想用LINQ
来做foreach (int i in indexes)
{
char[] ch = new char[1];
input.CopyTo(i, ch, 0, 1);
chars.Add(ch[0]);
}
答案 0 :(得分:8)
让我们看看你的代码是做什么的。
char[] ch = new char[1];
input.CopyTo(i, ch, 0, 1);
这是CopyTo
的文档:
将此实例中指定位置的指定数量的字符复制到Unicode字符数组中的指定位置。
因此,您始终将字符串的单个字符复制到长度为1的字符缓冲区。特别是对于这种情况,有一种更简单的方法 - 它甚至不涉及临时字符缓冲区:
char ch = input[i];
现在你的下一行变得更加简单:
chars.Add(ch);
所以,总的来说你有这个:
var ch = input[i];
chars.Add(ch);
此变量仅使用一次,显然可以在使用它的位置内联:
chars.Add(input[i]);
因此整个循环变为:
foreach (var i in indexes)
{
chars.Add(input[i]);
}
这是foreach
循环的一个特例,其中每次迭代计算"某些东西" (input[i]
)并且最后它添加了"某些东西"到集合(chars.Add
)。幸运的是,这也是一个非常典型的循环,可以很容易地变成LINQ。
首先,您需要识别源,这通常是您在foreach
上执行的对象:
indexes
然后,您需要识别选择器,这是计算"某些内容的代码"您正在添加,并将该代码传递给Select
方法:
.Select(i => input[i])
此时,你有这个:
indexes.Select(i => input[i]);
您可以按原样将其添加到列表中:
chars.AddRange(indexes.Select(i => input[i]));
但是如果你有特殊情况,列表是空的(例如,因为你刚刚创建它),那么你现在可能正在看这样的事情:
var chars = new List<char>();
chars.AddRange(indexes.Select(i => input[i]));
这也是一种非常常见的情况,ToList()
扩展方法可以进一步简化它。该方法基本上枚举了查询并为您创建列表,省去了调用构造函数和Add
或AddRange
方法的麻烦:
var chars = indexes.Select(i => input[i]).ToList();
答案 1 :(得分:3)
chars =
indexes
.Select(index => input[index])
.ToList();
如果其中一个索引超出范围,则会抛出,但原始代码也是如此。此外,如果您需要保留chars
中已有的内容,则可能需要连接。