我喜欢Python中的列表推导式,因为它们简洁地表示了对列表的转换。
然而,在其他语言中,我经常会写出类似以下的代码:
foreach (int x in intArray)
if (x > 3) //generic condition on x
x++
//do other processing
这个示例是用C#编写的,我认为LINQ可以帮助解决这个问题,但是是否有一些常见的编程结构可以替换这个稍微不太优雅的解决方案?也许有一些数据结构我没有考虑到吗?
在原始的foreach
循环中增加不会影响数组的内容,唯一的方法仍然是使用for
循环:
for(int i = 0; i < intArray.Length; ++i)
{
if(intArray[i] > 3) ++intArray[i];
}
Linq 的目的不是修改现有的集合或序列,而是基于现有的集合或序列创建新的序列。虽然可以使用 Linq 实现上述代码,但这略微违反了其目的:
var newArray1 = from i in intArray select ((i > 3) ? (i + 1) : (i));
var newArray2 = intArray.Select(i => (i > 3) ? (i + 1) : (i));
使用where
(或等效方法),就像其他答案中所示,将从结果序列中排除任何小于或等于3的值。
var intArray = new int[] { 10, 1, 20, 2 };
var newArray = from i in intArray where i > 3 select i + 1;
// newArray == { 11, 21 }
数组上有一个ForEach
方法,它允许您使用lambda函数而不是foreach
块,但对于任何超出方法调用的内容,我仍然建议使用foreach
。
intArray.ForEach(i => DoSomething(i));
intArray.Where(i => i > 3).ConvertAll();
DoStuff(intArray.Where(i => i 3));
Etc..
map(lambda x: foo(x + 1) filter(lambda x: x > 3, intArray))
还有列表推导式,可以在一条简单的语句中同时完成两件事:
[f(x + 1) for x in intArray if x > 3]
map(lambda x: test(x + 1) filter(lambda x: x > 3, arr))
在Ruby中:
intArray.select { |x| x > 3 }.each do |x|
# do other processing
end
或者如果“其他处理”只是一个简短的一行:
intArray.select { |x| x > 3 }.each { |x| something_that_uses x }
intArray.select { |x| x > 3 }.map { |x| do_something_to x }
根据语言和需要做什么,许多语言中所谓的“map”可能是您要寻找的东西。我不了解C#,但根据this页面,.NET 2.0将map称为“ConvertAll”。
“map”的含义非常简单-取一个列表,并对其每个元素应用一个函数,返回一个新列表。您可能还在寻找“filter”,它会给您一个满足另一个列表中谓词的项目列表。