使用另一个列表遍历一个列表。

4

我有两个列表,其中列表A的元素包含在列表B的元素中。注意,这个例子中顺序比较重要。

A = ['pent', 'tri', 'rec', 'oct', 'hex']
B = ['triangle', 'rectangle', 'pentangle', 'hexagon', 'octagon']

我想遍历A和B,无论在B中找到A的位置,都将其添加到字典中,然后再将其添加到另一个字典中。
d = {'prefix': a, 'shape':b}

l = [{'prefix': 'pent', 'shape':'pentangle'}, {'prefix':'tri' , 'shape':'triangle'}, {'prefix': 'rec', 'shape':'rectangle'},...]

我尝试使用zip函数,但由于B相对于A是无序的,所以它不起作用。

dict_list = []
for i,j in zip(A,B):
    if i in j:
        d = {'prefix': i, 'shape':j}
        dict_list.append(d)

我知道可以像“for i in A if i in B”这样做,但是我不知道如何将匹配的值放入我的字典中。

我认为这是一个非常基本的问题,我只是无法使它起作用。使用zip应该可以解决这个问题吗?我想也可能预先填充前缀,然后以某种方式使用它来查找形状,但是我不确定语法。我使用的列表在某些情况下有1000多个记录,因此无法手动执行此操作。

编辑:在我的示例中犯了一个错误:我正在使用的实际列表和字符串并非全部使用前缀。我不确定是否可以将其他方法替换为这些答案,但我感谢所有回答。我要解析的字符串是URL和URL的部分。 因此,A中充满了类似于'NA1234'的字符串,B则是'www.oops/NA1244/betterexample'


2
B 中是否可能有多个元素具有 A 中的前缀?例如 B = ['octagon', 'octahedron'] - wjandrea
在迭代它们之前,我将A和B转换为一个集合,因此不应该有重复项。 - S.Slusky
恩?这不能捕获重复的子串。例如,set(['octagon','octahedron']) == {'octagon','octahedron'} - wjandrea
1
我误解了你的问题。答案是肯定的,B 中可以包含多个包含 A 的元素。 - S.Slusky
2个回答

5
你可以使用列表推导式。这可能不是最有效的方法,但至少语法易于理解。
A = ['pent', 'tri', 'rec', 'oct', 'hex']
B = ['triangle', 'rectangle', 'pentangle', 'hexagon', 'octagon']

dict_list = [{'prefix': a, 'shape': b} for a in A for b in B if b.startswith(a)]

print(dict_list) # [{'prefix': 'pent', 'shape': 'pentangle'}, {'prefix': 'tri', 'shape': 'triangle'}, {'prefix': 'rec', 'shape': 'rectangle'}, {'prefix': 'oct', 'shape': 'octagon'}, {'prefix': 'hex', 'shape': 'hexagon'}]

有没有一种方法可以替换startswith(),如果匹配的部分不是前缀而是在字符串的中间。 'a in b' 在这里可以使用吗? - S.Slusky
2
@S.Slusky 当然可以使用 a in b 替代 b.startswith(a) - j1-lee

1
你可以尝试使用生成器编写列表推导式:
[{'prefix': x, 'shape': next(y for y in B if y.startswith(x))} for x in A]

输出:

[{'prefix': 'pent', 'shape': 'pentangle'},
 {'prefix': 'tri', 'shape': 'triangle'},
 {'prefix': 'rec', 'shape': 'rectangle'},
 {'prefix': 'oct', 'shape': 'octagon'},
 {'prefix': 'hex', 'shape': 'hexagon'}]

或者您可以先将B排序,使其与A的顺序相同:

B = sorted(B, key=lambda x: next(i for i, v in enumerate(A) if x.startswith(v)))

然后只需压缩:

zip

[{'prefix': x, 'shape': y} for x, y in zip(A, B)]

OP刚刚澄清B中有多个元素具有与A相同的前缀,因此在这里使用next()zip()是行不通的。 - wjandrea

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接