我喜欢 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));
在 C# 中,您可以对 IEnumerable 中的任何内容应用选择性处理,如下所示:
intArray.Where(i => i > 3).ConvertAll();
DoStuff(intArray.Where(i => i 3));
ETC..
在 Python 中,您有filter 和 map,可以满足您的需求:
map(lambda x: foo(x + 1) filter(lambda x: x > 3, intArray))
还有列表推导式可以在一个简单的语句中同时完成:
[f(x + 1) for x in intArray if x > 3]
在红宝石中:
intArray.select { |x| x > 3 }.each do |x|
# do other processing
end
或者如果“其他处理”是一个简短的单行:
intArray.select { |x| x > 3 }.each { |x| something_that_uses x }
最后,如果要返回一个新数组,其中包含对大于 3 的元素的处理结果:
intArray.select { |x| x > 3 }.map { |x| do_something_to x }
map(lambda x: test(x + 1) filter(lambda x: x > 3, arr))
取决于语言和您需要做什么,在许多语言中称为“地图”可能就是您正在寻找的。我不知道 C#,但根据这个页面,.NET 2.0 调用映射“ConvertAll”。
“map”的含义非常简单——获取一个列表,并将一个函数应用于它的每个元素,返回一个新列表。您可能还在寻找“过滤器”,它会为您提供满足另一个列表中谓词的项目列表。