【问题标题】:Python, list of pairs of elements from other listsPython,来自其他列表的元素对列表
【发布时间】:2019-08-13 09:38:44
【问题描述】:

我有一系列列表,请称它们为ABCDE。现在每个列表都有 5 个名称相同的元素,比如:

A: [ 'Cars_A', 'Planes_A', 'Houses_A', 'Bikes_A' ] 
B: [ 'Cars_B', 'Planes_B', 'Houses_B', 'Bikes_B' ]
etc..

我想要的是一个列表列表,格式为:

[ ['Cars_A', 'Planes_B'], ['Cars_A', 'Houses_B'], ['Cars_A', 'Bikes_B'], 
  ['Planes_A', 'Cars_B'], ['Planes_A', 'Houses_B'], ['Planes_A', 'Bikes_B'],
  ['Houses_A', 'Cars_B'], ['Houses_A', 'Planes_B'], ['Houses_A', 'Bikes_B'],
  ['Bikes_A', 'Cars_B'], ['Bikes_A', 'Planes_B'], ['Bikes_A', 'Houses_B'] ] 

可以看出,这个列表的规则是:

  • 一个元素不能与同一集合中的另一个元素组合在一起,例如,['Cars_A', 'Planes_A'] 是不允许的。
  • 一个元素不能与来自不同集合的相似元素分组,例如,['Cars_A', 'Cars_B'] 是不允许的。

我现在的尝试是对所有 5 个列表进行嵌套 for 循环,但我想尽可能避免这种情况。有任何想法吗?

【问题讨论】:

  • 已更改,它们都是列表,对此感到抱歉。
  • 你说我现在的尝试是为所有 5 个列表做嵌套的 for 循环。你能告诉我们吗?
  • 如何定义“相似”元素?是“直到下划线的相同文本”还是其他?
  • 相同的文字到下划线,是的。
  • 你说列表中的顺序是一样的,但是所有元素也是一样的(除了明显的“_A”,“_B”不同)?这个例子表明了。

标签: python arrays python-3.x list


【解决方案1】:

itertools.permutationsitertools.productfilter 一起使用:

import itertools

l = [['_'.join([i,g])for i in ['cars', 'planes', 'houses', 'bikes']] for g in 'ABCDE']
l    
[['cars_A', 'planes_A', 'houses_A', 'bikes_A'],
 ['cars_B', 'planes_B', 'houses_B', 'bikes_B'],
 ['cars_C', 'planes_C', 'houses_C', 'bikes_C'],
 ['cars_D', 'planes_D', 'houses_D', 'bikes_D'],
 ['cars_E', 'planes_E', 'houses_E', 'bikes_E']]

res = []
for sub in itertools.permutations(l, 2):
    res.extend(list(filter(lambda x: (x[0].split('_')[0]!=x[1].split('_')[0]), itertools.product(*sub))))    
res
[('cars_A', 'planes_B'),
 ('cars_A', 'houses_B'),
 ('cars_A', 'bikes_B'),
 ('planes_A', 'cars_B'),
 ('planes_A', 'houses_B'),
 ('planes_A', 'bikes_B'),
 ('houses_A', 'cars_B'),
 ...
 ('bikes_E', 'cars_D'),
 ('bikes_E', 'planes_D'),
 ('bikes_E', 'houses_D')]

【讨论】:

  • lambda 行很不合 Python,试图将一堆逻辑压缩到一行中
  • 使用排列很好
【解决方案2】:

这是使用itertools.combinations 的简单方法,让我们先制作所有对,然后再制作filter

from itertools import combinations

def filter_(tup):
    x, y = tup
    p1 = x.split('_')
    p2 = y.split('_')
    return (p1[0] != p2[0]) and (p1[1] != p2[1])


list(filter(filter_, combinations([*A, *B], 2)))

[('Cars_A', 'Planes_B'),
 ('Cars_A', 'Houses_B'),
 ('Cars_A', 'Bikes_B'),
 ('Planes_A', 'Cars_B'),
 ('Planes_A', 'Houses_B'),
 ('Planes_A', 'Bikes_B'),
 ('Houses_A', 'Cars_B'),
 ('Houses_A', 'Planes_B'),
 ('Houses_A', 'Bikes_B'),
 ('Bikes_A', 'Cars_B'),
 ('Bikes_A', 'Planes_B'),
 ('Bikes_A', 'Houses_B')]


list(filter(filter_, combinations([*A, *B, *C], 2)))

[('Cars_A', 'Planes_B'),
 ('Cars_A', 'Houses_B'),
 ('Cars_A', 'Bikes_B'),
 ('Cars_A', 'Planes_C'),
 ('Cars_A', 'Houses_C'),
 ('Cars_A', 'Bikes_C'),
 ('Planes_A', 'Cars_B'),
 ('Planes_A', 'Houses_B'),
 ('Planes_A', 'Bikes_B'),
 ('Planes_A', 'Cars_C'),
 ('Planes_A', 'Houses_C'),
 ('Planes_A', 'Bikes_C'),
 ('Houses_A', 'Cars_B'),
  ...

【讨论】:

    【解决方案3】:

    这是一种不用itertools 的方法,而是使用来自collections 模块的快速数据结构,名为deque

    from collections import deque
    A=[ 'Cars_A', 'Planes_A', 'Houses_A', 'Bikes_A' ] 
    B=[ 'Cars_B', 'Planes_B', 'Houses_B', 'Bikes_B' ]
    
    l=[deque(A),deque(B)]
    n = 0
    for i in l:
        i.rotate(n)
        n += 1
    m = zip(*l)
    print(list(m))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-05
      • 1970-01-01
      • 1970-01-01
      • 2018-01-17
      • 2022-01-25
      • 1970-01-01
      相关资源
      最近更新 更多