我正在尝试编写一个函数,它将从键中返回一个键列表(如果这是有意义的话)。例如,这是一本作者和类似作者的字典。
authors = {
'Ray Bradbury': ['Harlan Ellison', 'Robert Heinlein', 'Isaac Asimov', 'Arthur Clarke'],
'Harlan Ellison': ['Neil Stephenson', 'Kurt Vonnegut', 'Richard Morgan', 'Douglas Adams'],
'Kurt Vonnegut': ['Terry Pratchett', 'Tom Robbins', 'Douglas Adams', 'Neil Stephenson', 'Jeff Vandemeer'],
'Thomas Pynchon': ['Isaac Asimov', 'Jorges Borges', 'Robert Heinlein'],
'Isaac Asimov': ['Stephen Baxter', 'Ray Bradbury', 'Arthur Clarke', 'Kurt Vonnegut', 'Neil Stephenson'],
'Douglas Adams': ['Terry Pratchett', 'Chris Moore', 'Kurt Vonnegut']
}
我想出的功能就是:
def get_similar(author_list, author):
for item in author_list[author]:
return author_list[author]
仅返回第一个键的项目。我想让它返回所有类似的作者,如下:
get_similar(authors, 'Harlan Ellison')
['Terry Pratchett', 'Tom Robbins', 'Douglas Adams', 'Neil Stephenson',
'Jeff Vandemeer','Terry Pratchett', 'Chris Moore', 'Kurt Vonnegut']
在找到给定键(作者)的位置,查看为该键列出的项目,然后返回这些键的项目。在这种情况下,哈伦·埃里森有四位作者 - 尼尔·斯蒂芬森,库尔特·冯内古特,理查德·摩根和道格拉斯·亚当斯。该功能然后查找这些作者,并返回列出的项目 - Kurt Vonnegut返回Terry Pratchett,Tom Robbins,Douglas Adams,Neil Stephenson和Jeff Vandemeer,Douglas Adams返回Terry Pratchett,Chris Moore和Kurt Vonnegut,< / p>
重复是好的,我希望它按字母顺序排列(我假设你最后可以使用sort
命令)任何帮助都会非常感激,我很难过!
答案 0 :(得分:1)
我认为这就是你要找的东西。希望它能让你前进。
authors = {'Ray Bradbury': ['Harlan Ellison', 'Robert Heinlein', 'Isaac Asimov', 'Arthur Clarke'], 'Harlan Ellison': ['Neil Stephenson', 'Kurt Vonnegut', 'Richard Morgan', 'Douglas Adams'], 'Kurt Vonnegut': ['Terry Pratchett', 'Tom Robbins', 'Douglas Adams', 'Neil Stephenson', 'Jeff Vandemeer'], 'Thomas Pynchon': ['Isaac Asimov', 'Jorges Borges', 'Robert Heinlein'], 'Isaac Asimov': ['Stephen Baxter', 'Ray Bradbury', 'Arthur Clarke', 'Kurt Vonnegut', 'Neil Stephenson'], 'Douglas Adams': ['Terry Pratchett', 'Chris Moore', 'Kurt Vonnegut']}
def get_similar(authors, author):
retVal = []
for k, v in authors.items():
if k == author:
for value in v:
retVal.append(value)
if value in authors:
for v2 in authors[value]:
retVal.append(v2)
return sorted(retVal)
get_similar(作者,“Harlan Ellison”)回归 ['克里斯摩尔', '道格拉斯·亚当斯', '道格拉斯·亚当斯', '杰夫范德米尔', 'Kurt Vonnegut', 'Kurt Vonnegut', 'Neil Stephenson', 'Neil Stephenson', '理查德摩根', '特里普拉切特', '特里普拉切特', '汤姆罗宾斯']
我会留给你弄清楚如何删除重复项。
答案 1 :(得分:1)
你非常接近,但是在找到第一个类似作者的列表后,你应该将你找到的所有作者存储在列表中,然后在for
循环结束后将它们全部返回:
def get_similar(author_list, author):
similar_authors = []
for item in author_list[author]:
if item in author_list:
similar_authors.extend(author_list[item])
return similar_authors
请注意,我还添加了if
语句,以确保item
实际上是您词典中的键之一,这样您以后就不会收到错误(例如:&#39; Neil Stephenson&#39;在词典中作为其中一个值的成员,但不是关键词。)
额外信息:
(如果您有兴趣)
另一种选择是将您的功能转换为generator。这样做的好处是不必将所有相似的作者存储在一个列表中,而是yield
找到每个作者:
def get_similar2(author_list, author):
for item in author_list[author]:
if item in author_list:
for other_author in author_list[item]:
yield other_author
或者,如果您使用的是python 3.3+,可以使用yield from
表达式来简化此操作,以获得与get_similar2
中相同的代码:
def get_similar3(author_list, author):
for item in author_list[author]:
if item in author_list:
yield from author_list[item]
上面的所有三个函数/生成器都会给你相同的结果(只记得从生成器中获取所有值):
print(get_similar(authors, 'Harlan Ellison'))
['Terry Pratchett', 'Tom Robbins', 'Douglas Adams', 'Neil Stephenson', 'Jeff Vandemeer', 'Terry Pratchett', 'Chris Moore', 'Kurt Vonnegut']
print(list(get_similar2(authors, 'Harlan Ellison')))
['Terry Pratchett', 'Tom Robbins', 'Douglas Adams', 'Neil Stephenson', 'Jeff Vandemeer', 'Terry Pratchett', 'Chris Moore', 'Kurt Vonnegut']
print(list(get_similar3(authors, 'Harlan Ellison')))
['Terry Pratchett', 'Tom Robbins', 'Douglas Adams', 'Neil Stephenson', 'Jeff Vandemeer', 'Terry Pratchett', 'Chris Moore', 'Kurt Vonnegut']
答案 2 :(得分:1)
这是一个使用set和list comprehension的简单解决方案:
def get_similar(author_list, author):
similar = set(author_list.get(author, []))
similar.update(*[author_list.get(item, []) for item in similar])
return sorted(similar)
get_similar(authors, 'Harlan Ellison')
输出:
['Chris Moore', 'Douglas Adams', 'Jeff Vandemeer', 'Kurt Vonnegut',
'Neil Stephenson', 'Richard Morgan', 'Terry Pratchett', 'Tom Robbins']
答案 3 :(得分:1)
现在你正在做的事情将以for
循环的方式运行 - 你基本上只做一次查找并返回,因此你只得到一个条目。你需要做的是做你的查找,找到作者,然后对每个作者进行查找,然后冲洗并重复...最简单的方法是使用一点递归:
def get_similar(authors, author):
return [a for x in authors.pop(author, []) for a in [x] + get_similar(authors, x)]
get_similar(authors, 'Harlan Ellison')
# ['Neil Stephenson', 'Kurt Vonnegut', 'Terry Pratchett', 'Tom Robbins', 'Douglas Adams',
# 'Terry Pratchett', 'Chris Moore', 'Kurt Vonnegut', 'Neil Stephenson', 'Jeff Vandemeer',
# 'Richard Morgan', 'Douglas Adams']
然后你需要做的就是把它变成一个集合来摆脱重复,然后对它进行排序,或者如果你不介意轻微的性能损失(由于递归),你可以正确地做到这一点在你的功能中:
def get_similar(authors, author):
return sorted(set([a for x in authors.pop(author, []) for a in [x] + get_similar(authors, x)]))
# ['Chris Moore', 'Douglas Adams', 'Jeff Vandemeer', 'Kurt Vonnegut', 'Neil Stephenson', 'Richard Morgan', 'Terry Pratchett', 'Tom Robbins']
请记住,这会修改输入字典以避免无限递归,因此如果要保持authors
字典完整,请将函数调用为get_similar(authors.copy(), author)
。
答案 4 :(得分:0)
我会使用递归以这种方式找到类似的作者。来发现,想要返回重复项更加不方便(而且更危险,更慢)。
authors = {'Ray Bradbury': ['Harlan Ellison', 'Robert Heinlein', 'Isaac Asimov', 'Arthur Clarke'], 'Harlan Ellison': ['Neil Stephenson',
'Kurt Vonnegut', 'Richard Morgan', 'Douglas Adams'], 'Kurt Vonnegut': ['Terry Pratchett', 'Tom Robbins', 'Douglas Adams',
'Neil Stephenson', 'Jeff Vandemeer'], 'Thomas Pynchon': ['Isaac Asimov', 'Jorges Borges', 'Robert Heinlein'], 'Isaac Asimov':
['Stephen Baxter', 'Ray Bradbury', 'Arthur Clarke', 'Kurt Vonnegut', 'Neil Stephenson'], 'Douglas Adams': ['Terry Pratchett', 'Chris Moore', 'Kurt Vonnegut']}
def get_similar(author_list, author, currentList=[]):
for similar in author_list[author]:
if similar not in currentList:
currentList.append(similar)
if similar in authors:
get_similar(author_list, author, currentList)
return sorted(currentList)
print(get_similar(authors, "Harlan Ellison"))
返回:
['Douglas Adams', 'Kurt Vonnegut', 'Neil Stephenson', 'Richard Morgan']
答案 5 :(得分:0)
正在发生的事情是函数只接受一个返回来修复它,返回完整行而不重复
def get_similar(author_list, author):
return sorted(author_list[author])
答案 6 :(得分:0)
一种方法是使用列表推导+ itertools.chain
from itertools import chain
def get_similar(author_list, author):
return sorted(set(chain(*[v for k,v in authors.items() if k in authors[author]])))
get_similar(authors, 'Harlan Ellison')
#['Chris Moore', 'Douglas Adams', 'Jeff Vandemeer', 'Kurt Vonnegut', 'Neil Stephenson', 'Terry Pratchett', 'Tom Robbins']
答案 7 :(得分:0)
如果它是author
值中的一个元素,我不会在输出中包含参数list
。您可以使用list comprehension
:
def get_similar(author_list, author):
# Lists of similar authors
similar = [author_list[auth] for auth in author_list[author] if auth in author_list]
# Merge the lists and sort the authors. Do not include parameter author
return sorted(auth for sub in similar for auth in sub if auth != author)
authors = {
'Ray Bradbury': ['Harlan Ellison', 'Robert Heinlein', 'Isaac Asimov', 'Arthur Clarke'],
'Harlan Ellison': ['Neil Stephenson', 'Kurt Vonnegut', 'Richard Morgan', 'Douglas Adams'],
'Kurt Vonnegut': ['Terry Pratchett', 'Tom Robbins', 'Douglas Adams', 'Neil Stephenson', 'Jeff Vandemeer'],
'Thomas Pynchon': ['Isaac Asimov', 'Jorges Borges', 'Robert Heinlein'],
'Isaac Asimov': ['Stephen Baxter', 'Ray Bradbury', 'Arthur Clarke', 'Kurt Vonnegut', 'Neil Stephenson'],
'Douglas Adams': ['Terry Pratchett', 'Chris Moore', 'Kurt Vonnegut']
}
>>> get_similar(authors, 'Harlan Ellison')
['Chris Moore', 'Douglas Adams', 'Jeff Vandemeer', 'Kurt Vonnegut', 'Neil Stephenson', 'Terry Pratchett', 'Terry Pratchett', 'Tom Robbins']
>>> get_similar(authors, 'Ray Bradbury') # There's 'Ray Bradbury' in the values of 'Isaac Asimov'
['Arthur Clarke', 'Douglas Adams', 'Kurt Vonnegut', 'Kurt Vonnegut', 'Neil Stephenson', 'Neil Stephenson', 'Richard Morgan', 'Stephen Baxter']