C# 有什么可以与 Python 的列表推导式相媲美的吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/323032/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Does C# have anything comparable to Python's list comprehensions?
提问by minty
I want to generate a list in C#. I am missing python's list comprehensions. Is there a C# way to create collections on the fly like list comprehensions or generator expressions do in python?
我想在 C# 中生成一个列表。我缺少 python 的列表理解。是否有 C# 方法可以像 Python 中的列表推导式或生成器表达式那样动态创建集合?
采纳答案by Matt Campbell
If you are using C# 3.0 (VS2008) then LINQ to Objects can do very similar things:
如果您使用的是 C# 3.0 (VS2008),那么 LINQ to Objects 可以做非常相似的事情:
List<Foo> fooList = new List<Foo>();
IEnumerable<Foo> extract = from foo in fooList where foo.Bar > 10 select Foo.Name.ToUpper();
回答by Jon Skeet
Matt has mentioned query expressions. These are available for LINQ in general, by the way - not just LINQ to Objects. (For example, the same query applied to a LINQ to SQL datacontext would execute the filter and projection on the database.)
Matt 提到了查询表达式。顺便说一下,这些通常可用于 LINQ - 不仅仅是 LINQ to Objects。(例如,应用于 LINQ to SQL 数据上下文的相同查询将在数据库上执行过滤器和投影。)
The query expressions in C# 3 are simply syntactic sugar over writing normal C# code - although query expressions usually end up calling extension methods. (They don't have to, and the compiler doesn't care, but they usually do.) There are various things you can do with collections which aren't available in C# query expressions, but which are supported by method calls, so it's worth being aware of both kinds of syntax. For instance, Matt's query expression of:
C# 3 中的查询表达式只是编写普通 C# 代码的语法糖 - 尽管查询表达式通常最终会调用扩展方法。(他们不必这样做,编译器也不关心,但他们通常会这样做。)您可以对 C# 查询表达式中不可用但方法调用支持的集合执行多种操作,因此有必要了解这两种语法。例如,Matt 的查询表达式为:
List<Foo> fooList = new List<Foo>();
IEnumerable<string> extract = from foo in fooList where foo.Bar > 10 select foo.Name.ToUpper();
is "pre-processed" into:
被“预处理”成:
List<Foo> fooList = new List<Foo>();
IEnumerable<string> extract = fooList.Where(foo => foo.Bar > 10)
.Select(foo => foo.Name.ToUpper());
If you want to (say) filter based on the index of the value in the original collection, you can use an appropriate overload of Wherewhich is unavailable via query expressions:
如果您想(例如)根据原始集合中值的索引进行过滤,您可以使用适当的 Where 重载,该重载通过查询表达式不可用:
List<Foo> fooList = new List<Foo>();
IEnumerable<string> extract = fooList.Where((foo, index) => foo.Bar > 10 + index)
.Select(foo => foo.Name.ToUpper());
Or you could find the length of the longest name matching the criteria:
或者您可以找到符合条件的最长名称的长度:
List<Foo> fooList = new List<Foo>();
int longestName = fooList.Where((foo, index) => foo.Bar > 10 + index)
.Select(foo => foo.Name)
.Max();
(You don't haveto do the projection and max in separate methods - there's a Max
overload which takes a projection as well.)
(你不具备做投影,最大的不同的方法-有一个Max
过载,这需要投影为好。)
My point is that using extension methods you can very easily build up sophisticated queries.
我的观点是,使用扩展方法可以非常轻松地构建复杂的查询。
You mention Python generators as well - C# has this in the form of iterator blocks. Indeed, these are incredibly useful when implementing LINQ-like operators. (Because most of LINQ to Objects is based on extension methods, you can add your own operators which look "native" to LINQ - although you can't change the query expression syntax yourself.)
您还提到了 Python 生成器 - C# 以迭代器块的形式提供了它。实际上,这些在实现类似 LINQ 的运算符时非常有用。(因为大多数 LINQ to Objects 都基于扩展方法,所以您可以添加自己的运算符,这些运算符看起来像是 LINQ 的“本机”——尽管您不能自己更改查询表达式语法。)
回答by Ray
List<T>.ConvertAll
behaves just like list comprehensions by performing the same operation on every item on an existing list and then returning a new collection. This is an alternative to using Linq especially if you are still using .NET 2.0.
List<T>.ConvertAll
通过对现有列表中的每个项目执行相同的操作,然后返回一个新集合,其行为就像列表推导式一样。这是使用 Linq 的替代方法,尤其是在您仍在使用 .NET 2.0 的情况下。
In Python, a simple list comprehension example:
在 Python 中,一个简单的列表理解示例:
>>> foo = [1, 2, 3]
>>> bar = [x * 2 for x in foo]
>>> bar
[2, 4, 6]
For C# 3.0, you can pass a lambda function specifying what type of mapping function is needed.
对于 C# 3.0,您可以传递一个 lambda 函数,指定需要什么类型的映射函数。
public static void Main()
{
var foo = new List<int>{ 1, 2, 3};
var bar = foo.ConvertAll(x => x * 2); // list comprehension
foreach (var x in bar)
{
Console.WriteLine(x); // should print 2 4 6
}
}
For C# 2.0, you can use an anonymous method with the Converter
delegate to perform the equivalent.
对于 C# 2.0,您可以使用带有Converter
委托的匿名方法来执行等效操作。
public static void Main()
{
List<int> foo = new List<int>(new int[]{ 1, 2, 3});
List<int> bar = foo.ConvertAll(new Converter<int, int>(delegate(int x){ return x * 2; })); // list comprehension
foreach (int x in bar)
{
Console.WriteLine(x); // should print 2 4 6
}
}
(Note: the same can be done with Arrays using Array.ConvertAll
(注意:同样可以使用数组来完成 Array.ConvertAll
回答by Nachbars Lumpi
There's this:
有这个:
new List<FooBar> { new Foo(), new Bar() }
which is only a little longer than its python equivalent:
这仅比它的 python 等价物长一点:
[Foo(), Bar()]
And then there is this:
然后是这个:
public IEnumerable<FooBar> myFooBarGenerator() {
yield return new Foo();
yield return new Bar();
}
which is the python equivalent of:
这是python的等效项:
def myFooBarGenerator():
yield Foo()
yield Bar()
回答by Sна?ош?а?
I know this is very very late an answer, but I too wondered if C# has anything equivalent to python's list comprehension. Answers from both Matt Campbelland Jon Skeetshow how to extracta list from an existing one, as far as I understood. But a python's list comprehension can also create a list from scratch. So here is what I came up with.
我知道这是一个非常非常晚的答案,但我也想知道 C# 是否有任何与 python 的列表理解等效的东西。据我所知,来自Matt Campbell和Jon Skeet 的回答展示了如何从现有列表中提取列表。但是 Python 的列表推导式也可以从头开始创建列表。所以这就是我想出的。
First I will show the python list comprehension, and then its C# equivalent that I came up with.
首先,我将展示 python 列表推导式,然后是我想出的 C# 等价物。
The toy task is to create a string like this
玩具任务是创建一个像这样的字符串
cb01, cb02, cb02, ... , cb50
Python list comprehension:
Python列表理解:
s = ', '.join('cb{0:02}'.format(i+1) for i in range(50))
C# equivalent I came up with:
我想出的 C# 等价物:
string s = String.Join(", ", new Func<List<string>>( () =>
{
List<string> list = new List<string>();
foreach (int i in Enumerable.Range(1, 50))
list.Add(String.Format("cb{0:00}", i));
return list;
}).Invoke());
I am not sure if I over-did anything or not though.
不过,我不确定我是否做过头。
Edit:(from what Jon Skeet mentioned in his comment, a real one-liner equivalent to python's list comprehension)
编辑:(从 Jon Skeet 在他的评论中提到的,一个真正的单行相当于 python 的列表理解)
String.Join(", ", Enumerable.Range(1, 50).Select(x => $"cb{x:00}")))
Note that $
thing is a C# 6 feature. If you are still not using C# 6, you can go with the old String.Format()
way.
请注意,$
事物是C# 6 功能。如果您仍未使用 C# 6,则可以采用旧String.Format()
方法。