pro*_*eek 54 c# python linq list-comprehension
以下简单的LINQ代码
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();
Run Code Online (Sandbox Code Playgroud)
可以使用列表推导将其翻译成python,如下所示.
words = ["hello", "wonderful", "linq", "beautiful", "world"]
shortWords = [x for x in words if len(x) <=5]
print shortWords
Run Code Online (Sandbox Code Playgroud)
小智 58
(警告:猛犸象回答.直到第一条水平线的部分是一个很好的tl; dr部分,我想)
我不确定我是否有资格成为Python大师...但我对Python中的迭代有一个扎实的把握,所以让我们试试:)
首先:Afaik,LINQ查询是懒惰地执行 - 如果是这样的话,生成器表达式是一个更接近的Python概念(无论是方式,列表,字典和集合理解在概念上只是生成器表达式提供给list/dict/set构造函数! ).
此外,还有一个概念上的区别:正如名称所示,LINQ用于查询数据结构.List-/dict-/set comprehensions可以应用于此(例如,过滤和投影列表的项目).所以它们实际上不那么通用(正如我们将要看到的,LINQ中内置的很多东西都不是内置的).同样,生成器表达式是一种在某种程度上形成一次性前向迭代器的方法(我喜欢将它视为生成器函数的lambda,只有没有丑陋的long关键字;))而不是描述复杂查询的方法.它们重叠,是的,但它们并不相同.如果你想在Python中使用LINQ的所有功能,你将不得不编写一个完整的生成器.或者结合内置和内置的众多强大的发电机itertools
.
现在,用于LINQ功能的Python同行Jon Skeet命名为:
预测: (x.foo for ...)
过滤: (... if x.bar > 5)
- 连接(x在x.foo上连接y等于y.bar)
((x_item, next(y_item for y_item in y if x_item.foo == y_item.bar)) for x_item in x)
我想,最接近的是.
请注意,对于每个x_item,这不会遍历整个y,它只会获得第一个匹配.
- 组连接(x连接y在x.foo上等于y.bar到g)
这更难.Python没有匿名类型,但如果你不介意弄乱它们,它们很容易做到__dict__
:
class Anonymous(object):
def __init__(self, **kwargs):
self.__dict__ = kwargs
Run Code Online (Sandbox Code Playgroud)
然后,我们可以(Anonymous(x=x, y=y) for ...)
获取具有相应值的对象列表x
和y
成员列表.正确的做法通常是将结果提供给approriate类的构造函数,比如XY.
- 分组(按x.bar分组x.foo)
现在它变得毛茸茸......没有内置的方式,afaik.但是如果我们需要它,我们可以自己定义它:
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
Run Code Online (Sandbox Code Playgroud)
例:
>>> 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: [...], ...})
Run Code Online (Sandbox Code Playgroud)
但是,这要求我们分组的任何东西都是可以清洗的.有可能避免这种情况,如果有公共需求,我会做出准备.但就目前而言,我很懒惰:)
我们也可以只返回组的迭代没有我们通过分组的值,通过调用.values()
的结果(当然,我们可以养活这对list
得到的东西,我们可以索引并重复几次).但谁知道我们是否不需要团体价值观......
- 订购(按x.foo升序排序,y.bar降序)
排序需要特殊的语法?内置也sorted
适用于iterables:sorted(x % 2 for x in range(10))
或sorted(x for x in xs, key=attrgetter('foo'))
.默认情况下按升序排序,关键字参数reverse
按降序排列.
唉,通过多个属性进行分类并不容易,特别是在混合上升和下降时.嗯...食谱的主题?
- 中间变量(让tmp = x.foo)
不,在理解或生成器表达式中是不可能的 - 正如名称所说,它们应该是表达式(通常只跨越一行或两行).但是在发电机功能方面完全可能:
(x * 2 for x in iterable)
Run Code Online (Sandbox Code Playgroud)
用中间变量重写为生成器:
def doubles(iterable):
for x in iterable:
times2 = x * 2
yield times2
Run Code Online (Sandbox Code Playgroud)
扁平化: (c for s in ("aa","bb") for c in s )
请注意,尽管LINQ to Objects处理委托,但其他查询提供程序(例如LINQ to SQL)可以处理描述查询的表达式树,而不仅仅是呈现可执行委托.这允许将查询转换为SQL(或其他查询语言) - 再次,我不知道Python是否支持这种事情.但它是LINQ的重要组成部分.
Python绝对没有这样的东西.列表表达式一对一地对应于(可能嵌套的)for循环中的普通列表,生成器表达式与发生器一一对应.给定parser
和ast
模块,理论上可以编写用于将理解转换为例如SQL查询的库.但没有人关心.
Jon*_*eet 24
那么,你需要区分一些不同的东西:
如VB做的,但这里是它的C#不支持尽可能多的查询表达式中不支持:
select x.foo
)where x.bar > 5
)x join y on x.foo equals y.bar
)x join y on x.foo equals y.bar into g
)group x.foo by x.bar
)orderby x.foo ascending, y.bar descending
)let tmp = x.foo
)from x in y from z in x
)我不知道Python的列表推导中有多少是直接支持的.
请注意,尽管LINQ to Objects处理委托,但其他查询提供程序(例如LINQ to SQL)可以处理描述查询的表达式树,而不仅仅是呈现可执行委托.这允许将查询转换为SQL(或其他查询语言) - 再次,我不知道Python是否支持这种事情.但它是LINQ的重要组成部分.
Rob*_*ire 17
通过使用asq Python包,您可以轻松地在Python中完成大多数事情,您可以使用LINQ-for-objects在C#中完成.使用asq,您的Python示例变为:
from asq.initiators import query
words = ["hello", "wonderful", "linq", "beautiful", "world"]
shortWords = query(words).where(lambda x: len(x) <= 5)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
15203 次 |
最近记录: |