我有一个嵌套列表,想将两个项目制成乘积。
test = [[('juice', 'NOUN'), ('orange', 'FLAVOR')],
[('juice', 'NOUN'), ('orange', 'FLAVOR'), ('lemon', 'FLAVOR')],
[('orange', 'FLAVOR'), ('chip', 'NOUN')]]
我期望的是这样的:
[(('juice', 'NOUN'), ('lemon', 'FLAVOR')),
(('juice', 'NOUN'), ('chip', 'NOUN')),
(('orange', 'FLAVOR'), ('lemon', 'FLAVOR')),
(('orange', 'FLAVOR'), ('chip', 'NOUN')),
(('lemon', 'FLAVOR'), ('chip', 'NOUN'))]
这就是说,我想跨列表进行排列,但仅针对唯一项。我更喜欢使用itertools
。以前,我尝试过list(itertools.product(*test))
,但是我意识到它将产生嵌套列表长度的乘积...
我当前的代码:
unique_list = list(set(itertools.chain(*test)))
list(itertools.combinations(unique_list, 2))
我的想法是首先获取嵌套列表中的唯一项,因此嵌套列表将为[[('juice', 'NOUN'), ('orange', 'FLAVOR')], [('lemon', 'FLAVOR')], [('chip', 'NOUN')]]
,然后使用itertools.combinations
进行置换。但是,它会在列表中排列(即果汁和橙子一起出现),这是我不希望出现在结果中的。
答案 0 :(得分:1)
这可以满足您的要求,无需将原始列表的大小固定为3:
输入:
test = [[('juice', 'NOUN'), ('orange', 'FLAVOR')],
[('juice', 'NOUN'), ('orange', 'FLAVOR'), ('lemon', 'FLAVOR')],
[('juice', 'NOUN'), ('chip', 'NOUN')]]
首先,重新格式化输入以删除重复项(请参见注释1):
test = [[x for x in sublist if x not in sum(test[:i], [])] for i, sublist in enumerate(test)]
最后,获取product中的combinations。
from itertools import combinations, product
for c in combinations(test, 2):
for x in product(*c):
print(x)
产生:
(('juice', 'NOUN'), ('lemon', 'FLAVOR'))
(('orange', 'FLAVOR'), ('lemon', 'FLAVOR'))
(('juice', 'NOUN'), ('chip', 'NOUN'))
(('orange', 'FLAVOR'), ('chip', 'NOUN'))
(('lemon', 'FLAVOR'), ('chip', 'NOUN'))
sum(test[:i], [])
的神奇之处在于将所有先前的子列表“相加”在一起,仅执行一次成员资格检查。对于紧凑性和样式点,还有上述的列表理解版本:
res = [x for c in combinations(test, 2) for x in product(*c)]