Ste*_*aly 28 python dictionary list-comprehension list
我正在尝试编写一个列表理解语句,如果它当前未包含在列表中,则只会添加一个项目.有没有办法检查当前正在构建的列表中的当前项?这是一个简短的例子:
输入
{
"Stefan" : ["running", "engineering", "dancing"],
"Bob" : ["dancing", "art", "theatre"],
"Julia" : ["running", "music", "art"]
}
Run Code Online (Sandbox Code Playgroud)
产量
["running", "engineering", "dancing", "art", "theatre", "music"]
Run Code Online (Sandbox Code Playgroud)
代码不使用列表理解
output = []
for name, hobbies in input.items():
for hobby in hobbies:
if hobby not in output:
output.append(hobby)
Run Code Online (Sandbox Code Playgroud)
我的尝试
[hobby for name, hobbies in input.items() for hobby in hobbies if hobby not in ???]
Run Code Online (Sandbox Code Playgroud)
gec*_*kon 36
您可以使用set
和设置理解:
{hobby for name, hobbies in input.items() for hobby in hobbies}
Run Code Online (Sandbox Code Playgroud)
正如m.wasowski所说,我们不使用name
这里,所以我们可以使用item.values()
:
{hobby for hobbies in input.values() for hobby in hobbies}
Run Code Online (Sandbox Code Playgroud)
如果你真的需要一个列表作为结果,你可以这样做(但请注意,通常你可以使用集合没有任何问题):
list({hobby for hobbies in input.values() for hobby in hobbies})
Run Code Online (Sandbox Code Playgroud)
Wil*_*sem 16
正如这个答案所暗示的那样:你可以使用唯一性过滤器:
def f7(seq):
seen = set()
seen_add = seen.add
return [x for x in seq if not (x in seen or seen_add(x))]
Run Code Online (Sandbox Code Playgroud)
并致电:
>>> f7(hobby for name, hobbies in input.items() for hobby in hobbies)
['running', 'engineering', 'dancing', 'art', 'theatre', 'music']
Run Code Online (Sandbox Code Playgroud)
我会单独实现唯一性过滤器,因为设计规则说"不同的东西应该由不同的类/方法/组件/处理".此外,您可以根据需要重复使用此方法.
另一个优点是 - 如链接答案所写- 保留了项目的顺序.对于某些应用程序,这可能是必要的.
套和词典是你的朋友:
from collections import OrderedDict
from itertools import chain # 'flattens' collection of iterables
data = {
"Stefan" : ["running", "engineering", "dancing"],
"Bob" : ["dancing", "art", "theatre"],
"Julia" : ["running", "music", "art"]
}
# using set is the easiest way, but sets are unordered:
print {hobby for hobby in chain.from_iterable(data.values())}
# output:
# set(['art', 'theatre', 'dancing', 'engineering', 'running', 'music'])
# or use OrderedDict if you care about ordering:
print OrderedDict(
(hobby, None) for hobby in chain.from_iterable(data.values())
).keys()
# output:
# ['dancing', 'art', 'theatre', 'running', 'engineering', 'music']
Run Code Online (Sandbox Code Playgroud)
如果你真的想要一个listcomp而且只需要一个list-comp,你就可以做到
>>> s = []
>>> [s.append(j) for i in d.values() for j in i if j not in s]
[None, None, None, None, None, None]
>>> s
['dancing', 'art', 'theatre', 'running', 'engineering', 'music']
Run Code Online (Sandbox Code Playgroud)
这里s
是副作用的结果,d
是你原来的字典.这里的独特优势在于您可以保留订单,这与其他大多数答案不同.
注意:这是一种糟糕的方式,因为它利用了list-comp,结果是副作用.不要这样做,这个答案只是告诉你,你可以单独使用list comp来实现它
还有另一种写作方式,它更具描述性,你不需要嵌套(双重for
)理解:
output = set.union(*[set(hobbies) for hobbies in input_.values()])
Run Code Online (Sandbox Code Playgroud)
当你将输入表示为更概念上的声音时,即使用每个人的爱好设置(因为那里也不应该重复),这就变得更好了:
input_ = {
"Stefan" : {"running", "engineering", "dancing"},
"Bob" : {"dancing", "art", "theatre"},
"Julia" : {"running", "music", "art"}
}
output = set.union(*input_.values())
Run Code Online (Sandbox Code Playgroud)
列表理解不适合这个问题.我认为一套理解会更好,但是由于这已经在另一个答案中显示,我将展示一种用紧凑的单行解决这个问题的方法:
list(set(sum(hobbies_dict.values(), [])))
Run Code Online (Sandbox Code Playgroud)
另一个使用按位或运算符的有趣解决方案,它用作集合的联合运算符:
from operator import or_
from functools import reduce # Allowed, but unnecessary in Python 2.x
list(reduce(or_, map(set, hobbies_dict.values())))
Run Code Online (Sandbox Code Playgroud)
或者(无意的双关语,我发誓),而不是使用按位或运算符,只需使用set.union
并传递值的解压缩集映射.无需导入or_
和reduce
!这个想法的灵感来自Thijs van Dien的回答.
list(set.union(*map(set, hobbies_dict.values())))
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
11474 次 |
最近记录: |