Python的名单COM prehension VS .NET的LINQ [英] Python's list comprehension vs .NET LINQ

查看:114
本文介绍了Python的名单COM prehension VS .NET的LINQ的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面简单的LINQ code

The following simple LINQ code

string[] words = { "hello", "wonderful", "linq", "beautiful", "world" };

// Get only short words
var shortWords =
  from word in words
  where word.Length <= 5
  select word;

// Print each word out
shortWords.Dump();

可以用列表COM prehension如下被翻译成蟒蛇。

can be translated into python using list comprehension as follows.

words = ["hello", "wonderful", "linq", "beautiful", "world"]
shortWords = [x for x in words if len(x) <=5]
print shortWords


  • 是LINQ只是一个想法落实列表COM prehension?

  • 什么的例子可能是LINQ可以做,但名单COM prehension不能做。

  • 推荐答案

    (警告:未来猛犸答案部分到第一个水平线成为一名优秀的文艺青年最爱的部分,我想)

    (Warning: Mammoth answer ahead. The part up to the first horizontal line makes a good tl;dr section, I suppose)

    我不知道我是否有资格作为Python的大师......但我有在Python迭代扎实掌握,所以让我们试试:)

    I'm not sure if I qualify as Python guru... but I have a solid grasp on iteration in Python, so let's try :)

    第一关:据我所知,LINQ查询懒洋洋地执行 - 如果是这样的话,发电机前pressions是接近的Python概念(无论哪种方式,列表 - ,dict-和组COM prehensions在概念刚刚产生联邦快递pressions到列表/字典/集的构造!)。

    First off: Afaik, LINQ queries are executed lazily - if that's the case, generator expressions are a closer Python concept (either way, list-, dict- and set comprehensions are conceptually just generator expressions fed to the list/dict/set constructor!).

    另外,还有一个概念上的差异:LINQ是,正如它的名字说,查询的数据结构。列表 - / dict- /组COM prehensions这是可能的应用(例如过滤和投影列表中的项目)。因此,他们实际上一般较小(我们将会看到,建成LINQ很多事情不是内置了)。同样,发电机前pressions是制订一个一次性的前向迭代就地(我喜欢把它看作拉姆达发电机的功能,只是没有一个丑陋的,长的关键字;)的方式),而不是一种方法,描述一个复杂的查询。它们重叠,是的,但它们并不相同。如果你想LINQ在Python的所有功能,你将不得不写一个完全成熟的发电机。或合并众多功能强大的发电机的内置和和itertools

    Also, there is a conceptual difference: LINQ is for, as the name says, querying data structures. List-/dict-/set comprehensions are possible application of this (e.g. filtering and projecting the items of a list). So they are in fact less general (as we will see, many things built into LINQ are not built into them). Likewise, generator expressions are a way to formulate an one-time forward iterator in-place (I like to think of it as lambda for generator functions, only without an ugly, long keyword ;) ) and not a way to describe a complex query. They overlap, yes, but they are not identical. If you want all the power of LINQ in Python, you will have to write a fully-fledged generator. Or combine the numerous powerful generators built-in and in itertools.

    现在,巨蟒同行的LINQ功能乔恩斯基特命名为:

    Now, Python counterparts for the LINQ capabilities Jon Skeet named:

    预测:(x.foo为...)

    过滤:(...如果x.bar→5)


        
    • 联接(X加入Y开x.foo等于y.bar)

    •   

    最接近的事情将是((x_item,下一个(y_item为y中,如果x_item.foo == y_item.bar))为x中x_item y_item),我假设。

    The closest thing would be((x_item, next(y_item for y_item in y if x_item.foo == y_item.bar)) for x_item in x), I suppose.

    请注意,这不会对整个Ÿ每个迭代x_item,它只会得到第一个匹配。

    Note that this will not iterate over the whole y for each x_item, it will only get the first match.


        
    • 组加入(X加入Y开x.foo等于y.bar到G)

    •   

    这是更难。 Python没有匿名类型,虽然都是小事做自己,如果你不介意搞乱 __ __字典

    This is harder. Python doesn't have anonymous types, though they are trivial to do yourself if you don't mind messing with __dict__:

    class Anonymous(object):
        def __init__(self, **kwargs):
            self.__dict__ = kwargs
    

    然后,我们可以做(无名氏(X = X,Y = Y)为...)来得到那些有无<$ C $对象的列表C> X 和成员各自的值。
    正确的做法通常是喂养的结果,一个approriate类的构造函数,说,XY。

    Then, we could do (Anonymous(x=x, y=y) for ...) to get a list of objects that are have x and y members with the respective values. The right thing is usually feeding the results to the constructor of an approriate class, say, XY.


        
    • 分组(由x.bar组x.foo)

    •   

    现在它变得毛茸茸的... ...有没有内置的方式,据我所知。但是,我们可以将其定义我们自己,如果我们需要它:

    Now it gets hairy... there is no build-in way, afaik. But we can define it ourself if we need it:

    from collections import defaultdict
    
    def group_by(iterable, group_func):
        groups = defaultdict(list)
        for item in iterable:
            groups[group_func(item)].append(item)
        return groups
    

    例如:

    >>> from operator import attrgetter
    >>> group_by((x.foo for x in ...), attrgetter('bar'))
    defaultdict(<class 'list'>, {some_value_of_bar: [x.foo of all x where x.bar == some_value_of_bar], some_other_value_of_bar: [...], ...})
    

    这要求无论我们GROUP BY是哈希的,虽然。这是可能的,以避免这种情况,我会做一个刺,如果有市民的需求。但现在,我在懒惰:)

    This requires whatever we group by to be hashable, though. It's possible to avoid this, and I'll make a stab if there is public demand. But for now, I'm being lazy :)

    我们也可以只返回组的迭代不归我们的价值观,通过调用 .values​​()的结果(当然,我们可以养活的列表来得到的东西,我们可以索引并重复几次)。但谁知道,如果我们将不再需要在组值...

    We can also just return an iterable of groups without the values we grouped by, by calling .values() on the result (of course we can feed that to list to get something we can index and iterate several times). But who knows if we won't need the group values...


        
    • 排序(排序依据x.foo上升,y.bar降序)

    •   

    排序需要特殊的语法?集结在整理适用于iterables,太:排序(X%2在范围X(10))分类(X对于x在XS,关键= attrgetter('富'))。升序排列默认情况下,关键字参数逆转给降序排列。

    Sorting needs special syntax? The build-in sorted works for iterables, too: sorted(x % 2 for x in range(10)) or sorted(x for x in xs, key=attrgetter('foo')). Sorted ascending by default, the keyword argument reverse gives descending order.

    唉,据我所知由多个属性进行分类,不是那么容易,混合升序和降序时尤其如此。嗯...对配方的主题?

    Alas, afaik sorting by multiple attributes is not that easy, especially when mixing ascending and descending. Hmm... topic for a recipe?


        
    • 中间变量(让TMP = x.foo)

    •   

    没有,而不是在COM prehensions或发电机前pressions可能 - 他们是,正如它的名字说,应该是前pressions(通常只跨越一个或两行)。这是完全有可能在发生器功能,虽然:

    No, not possible in comprehensions or generator expressions - they are, as the name says, supposed to be expressions (and usually only span one or two lines). It's perfectly possible in generator function, though:

    (x * 2 for x in iterable)
    

    改写为与中间变量发生器:

    rewritten as generator with intermediate variable:

    def doubles(iterable):
        for x in iterable:
            times2 = x * 2
            yield times2
    

    压扁:(C为在了C S IN(AA,BB))

    请注意,虽然LINQ与代表对象的交易,其他查询供应商(例如LINQ to SQL中)可以处理的前pression树,描述了查询,而不是仅仅presenting可执行的代表。这将允许查询翻译成SQL(或其他查询语言) - 再次,我不知道的Python是否支持之类的事情与否。这是LINQ的显著部分虽然。

    Note that although LINQ to Objects deals with delegates, other query providers (e.g. LINQ to SQL) can deal in expression trees which describe the query instead of just presenting executable delegates. This allows the query to be translated into SQL (or other query languages) - again, I don't know whether Python supports that sort of thing or not. It's a significant part of LINQ though.

    的Python绝对没有做这样的事情。列表前pressions对应一对一到积累在一个(可能是嵌套)for循环的纯列表,发电机前pressions对应一到一个发电机。
    鉴于解析器 AST 模块,有可能的在理论上的写库转换一个COM prehension成如SQL查询。但是,没有人在乎。

    Python definitely does no such thing. List expressions correspond one-to-one to accumulating a plain list in a (possibly nested) for-loop, generator expressions correspond one-to-one to a generator. Given the parser and ast module, it would be possible in theory to write a library for converting a comprehension into e.g. an SQL query. But nobody cares to.

    这篇关于Python的名单COM prehension VS .NET的LINQ的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆