C有什么可以与Python的列表理解相媲美的吗?

2024-03-29 12:14:39 发布

您现在位置:Python中文网/ 问答频道 /正文


Tags: python
3条回答

如果您使用的是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();

Matt提到了查询表达式。顺便说一句,这些通常可用于LINQ,而不仅仅是LINQ to对象。(例如,应用于linqtosqldatacontext的同一查询将在数据库上执行筛选和投影。)

C#3中的查询表达式只是编写普通C#代码时的语法糖,尽管查询表达式通常最终调用extension methods。(它们不必这样做,编译器也不在乎,但它们通常会这样做。)对于在C查询表达式中不可用但由方法调用支持的集合,可以做很多事情,因此值得注意这两种语法。例如,Matt的查询表达式:

List<Foo> fooList = new List<Foo>();
IEnumerable<string> extract = from foo in fooList where foo.Bar > 10 select foo.Name.ToUpper();

“预处理”为:

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

如果要(比方说)基于原始集合中值的索引进行筛选,可以使用通过查询表达式不可用的appropriate overload of Where

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

或者可以找到与条件匹配的最长名称的长度:

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

(您不需要在单独的方法中使用来执行projection和max——还有一个Max重载也需要一个projection。)

我的观点是,使用扩展方法可以非常容易地构建复杂的查询。

您还提到了Python生成器-C以iterator blocks的形式提供了它。实际上,在实现类似LINQ的操作符时,这些方法非常有用。(因为大多数LINQ to对象都是基于扩展方法的,所以您可以添加自己的操作符,这些操作符看起来像LINQ的“原生”操作符——尽管您自己不能更改查询表达式语法。)

^{}的行为就像列表理解一样,对现有列表中的每个项执行相同的操作,然后返回一个新集合。这是使用Linq的一种替代方法,特别是当您仍在使用.NET 2.0时。

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

>>> foo = [1, 2, 3]
>>> bar = [x * 2 for x in foo]
>>> bar
[2, 4, 6]

对于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
    }
}

对于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
    }
}

(注意:使用^{}的数组也可以这样做)

相关问题 更多 >