C#有没有与Python的列表推导相媲美的东西?

min*_*nty 19 c# python list-comprehension list

我想在C#中生成一个列表.我错过了python的列表推导.是否有一种C#方式来动态创建集合,如列表推导或生成器表达式在python中做?

Mat*_*ell 22

如果您使用的是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();
Run Code Online (Sandbox Code Playgroud)


Jon*_*eet 15

Matt提到了查询表达式.顺便说一下,这些可用于LINQ - 不仅仅是LINQ to Objects.(例如,应用于LINQ to SQL datacontext的相同查询将执行数据库上的过滤器和投影.)

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();
Run Code Online (Sandbox Code Playgroud)

被"预处理"成:

List<Foo> fooList = new List<Foo>();
IEnumerable<string> extract = fooList.Where(foo => foo.Bar > 10)
                                     .Select(foo => foo.Name.ToUpper());
Run Code Online (Sandbox Code Playgroud)

如果您希望(比方说)基于原始集合中的值的索引进行过滤,则可以使用通过查询表达式不可用的Where适当重载:

List<Foo> fooList = new List<Foo>();
IEnumerable<string> extract = fooList.Where((foo, index) => foo.Bar > 10 + index)
                                     .Select(foo => foo.Name.ToUpper());
Run Code Online (Sandbox Code Playgroud)

或者您可以找到符合条件的最长名称的长度:

List<Foo> fooList = new List<Foo>();
int longestName = fooList.Where((foo, index) => foo.Bar > 10 + index)
                         .Select(foo => foo.Name)
                         .Max();
Run Code Online (Sandbox Code Playgroud)

(你不必须做的不同的方法投影和最大-有一个Max过载,这需要投影为好.)

我的观点是,使用扩展方法可以非常轻松地构建复杂的查询.

你也提到了Python生成器--C#以迭代器块的形式提供它.实际上,这些在实现类似LINQ的运算符时非常有用.(因为LINQ to Objects的大多数都是基于扩展方法的,所以你可以添加自己看起来像LINQ"本机"的运算符 - 虽然你不能自己改变查询表达式语法.)


Ray*_*ega 5

List<T>.ConvertAll通过对现有列表上的每个项执行相同的操作然后返回新集合,行为就像列表推导一样.如果您仍在使用.NET 2.0,这是使用Linq的替代方法.

在Python中,一个简单的列表理解示例:

>>> foo = [1, 2, 3]
>>> bar = [x * 2 for x in foo]
>>> bar
[2, 4, 6]
Run Code Online (Sandbox Code Playgroud)

对于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
    }
}
Run Code Online (Sandbox Code Playgroud)

对于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
    }
}
Run Code Online (Sandbox Code Playgroud)

(注意:使用Arrays可以完成相同的操作 Array.ConvertAll