我正在尝试使用列表推导来生成一个新列表,该列表包含从list1直接跟随(冒号后)的字母,其中list2中的单词以该特定字母开头。我设法使用嵌套for循环对此进行编码,如下所示:
list1=["A","B"]
list2=["Apple","Banana","Balloon","Boxer","Crayons","Elephant"]
newlist=[]
for i in list1:
newlist.append(i+":")
for j in list2:
if j[0]==i:
newlist[-1]+=j+","
产生预期结果:['A:Apple,', 'B:Banana,Balloon,Boxer,']
尝试使用列表理解相同,我想出了以下内容:
list1=["A","B"]
list2=["Apple","Banana","Balloon","Boxer","Crayons","Elephant"]
newlist=[i+":"+j+"," for i in list1 for j in list2 if i==j[0]]
导致:['A:Apple,', 'B:Banana,', 'B:Balloon,', 'B:Boxer,']
每次找到带有该首字母的单词时,会在newlist
中创建一个新项目,而我的意图是每个字母有一个项目。
有没有办法编辑列表推导代码以获得与使用嵌套for循环相同的结果?
答案 0 :(得分:2)
您需要做的就是删除第二个for
循环并将其替换为','.join(matching_words)
调用,现在您在字符串连接中使用j
:
newlist = ['{}:{}'.format(l, ','.join([w for w in list2 if w[0] == l])) for l in list1]
这不是非常有效;你为每个字母循环所有 list2
中的单词。为了有效地执行此操作,您最好将列表预处理为字典:
list2_map = {}
for word in list2:
list2_map.setdefault(word[0], []).append(word)
newlist = ['{}:{}'.format(l, ','.join(list2_map.get(l, []))) for l in list1]
第一个循环构建一个字典,将首字母映射到单词列表,这样您就可以直接使用这些列表而不是使用嵌套列表理解。
演示:
>>> list1 = ['A', 'B']
>>> list2 = ['Apple', 'Banana', 'Balloon', 'Boxer', 'Crayons', 'Elephant']
>>> list2_map = {}
>>> for word in list2:
... list2_map.setdefault(word[0], []).append(word)
...
>>> ['{}:{}'.format(l, ','.join(list2_map.get(l, []))) for l in list1]
['A:Apple', 'B:Banana,Balloon,Boxer']
上述算法在所有list2
中循环两次,在list1
之后循环两次,使其成为O(N)线性算法(将单个单词添加到list2
或单个字母以list1
增加固定金额的时间量。对于list2
中的每个字母,您的版本会在list1
上循环一次,使其成为O(NM)算法,每当您添加字母或单词时,都会增加指数级别的时间。
要将其添加到数字中,如果您展开list1
以涵盖所有26个ASCII大写字母并展开list2
以包含1000个字,那么您的方法(扫描所有list2
的单词给定的字母)会做26000步。我的版本,包括预先构建地图,只需要2026步。如果list2
包含100万字,则您的版本必须生成2600万个步骤,耗费200万个和26个。
答案 1 :(得分:2)
list1=["A","B"]
list2=["Apple","Banana","Balloon","Boxer","Crayons","Elephant"]
res = [l1 + ':' + ','.join(l2 for l2 in list2 if l2.startswith(l1)) for l1 in list1]
print(res)
# ['A:Apple', 'B:Banana,Balloon,Boxer']
但是阅读起来似乎很复杂,所以我建议使用嵌套循环。您可以创建生成器以提高可读性(如果您认为此版本更具可读性):
def f(list1, list2):
for l1 in list1:
val = ','.join(l2 for l2 in list2 if l2.startswith(l1))
yield l1 + ':' + val
print(list(f(list1, list2)))
# ['A:Apple', 'B:Banana,Balloon,Boxer']