我有这样的代码,可以根据自己的条件从一个列表中列出4个列表。拆分取决于列表元素的符号。 就像我想获取所有正数的列表,列出第一个元素为正,第二个元素为负的列表,等等...以及所有这样的组合。 当所有列表仅包含2个元素时,使用过滤器轻松创建4个列表即可。
vals=[(0, 0), (0, 1), (0, -1), (1, 0), (1, 1), (1, -1), (-1, 0), (-1, 1), (-1, -1)]
new_f=list(filter(lambda x:x[0]>=0,vals))
new_f=list(filter(lambda x:x[1]>=0,new_f))
print(new_f)
new_f=list(filter(lambda x:x[0]<=0,vals))
new_f=list(filter(lambda x:x[1]>=0,new_f))
print(new_f)
new_f=list(filter(lambda x:x[0]>=0,vals))
new_f=list(filter(lambda x:x[1]<=0,new_f))
print(new_f)
new_f=list(filter(lambda x:x[0]<=0,vals))
new_f=list(filter(lambda x:x[1]<=0,new_f))
print(new_f)
这是我的输出:
[(0, 0), (0, 1), (1, 0), (1, 1)]
[(0, 0), (0, 1), (-1, 0), (-1, 1)]
[(0, 0), (0, -1), (1, 0), (1, -1)]
[(0, 0), (0, -1), (-1, 0), (-1, -1)]
但是,如果我的元素的长度为3或更多,我怎么能不写所有条件呢(对于len = 4,将有2 ** 3种情况和2 ** 4种情况) 例如,这是我对n = 3的输入,以及当我想通过“没有否定”和“第一个负数而不是其他负数”进行过滤时的情况示例。
vals=[(0, 0, 0), (0, 0, 1), (0, 0, -1), (0, 1, 0), (0, 1, 1), (0, 1, -1), (0, -1, 0), (0, -1, 1), (0, -1, -1), (1, 0, 0), (1, 0, 1), (1, 0, -1), (1, 1, 0), (1, 1, 1), (1, 1, -1), (1, -1, 0), (1, -1, 1), (1, -1, -1), (-1, 0, 0), (-1, 0, 1), (-1, 0, -1), (-1, 1, 0), (-1, 1, 1), (-1, 1, -1), (-1, -1, 0), (-1, -1, 1), (-1, -1, -1)]
new_f=list(filter(lambda x:x[0]>=0,vals))
new_f=list(filter(lambda x:x[1]>=0,new_f))
new_f=list(filter(lambda x:x[2]>=0,new_f))
print(new_f)
new_f=list(filter(lambda x:x[0]<=0,vals))
new_f=list(filter(lambda x:x[1]>=0,new_f))
new_f=list(filter(lambda x:x[2]>=0,new_f))
print(new_f)
此处输出:
[(0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1), (1, 0, 0), (1, 0, 1), (1, 1, 0), (1, 1, 1)]
[(0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1), (-1, 0, 0), (-1, 0, 1), (-1, 1, 0), (-1, 1, 1)]
因此,我需要对该过程进行某种程度的自动化,以使其与更长的数组配合使用。
答案 0 :(得分:2)
列出列表。每个大列表的索引是比较的二进制方向:1
或True
代表正数,0
或False
代表负数。称为mask
。
遍历所有可能的掩码,从0到2 ^ n-1。对于每个蒙版,将布尔向量转换为系数序列。例如,掩码9
是二进制1001
,系数序列为[1,-1,-1、1]。将元组乘以面罩;例如
(0, 1, -1, 1) * [1, -1, -1, 1] => [0, -1, 1, 1]
根据候选人列表中的all
和mask
,使用element
函数过滤整个向量。
all(bit >= 0 for bit in
[element[i] * mask[i] for i in len(element)])
现在,将其包装在循环中,以循环访问掩码值。如果足够持久,则可以使用all
和嵌套的理解,在一行代码中创建2 ^ n个过滤列表的整个列表。我建议将其留给深夜黑客,而不是解决问题。
还请注意,itertools.permutations
很高兴为您生成掩码。
答案 1 :(得分:1)
您可以在两个过滤器函数中使用itertools.product
,输入中元组的大小为repeat
,然后zip
过滤器函数在每个元组中仅包含单个项如果满足所有过滤条件,则输出元组:
[[t for t in vals if all(f(i) for (f, i) in zip(filters, t))] for filters in product(((0).__le__, (0).__ge__), repeat=len(vals[0]))]
以便您输入示例内容:
vals = [(0, 0, 0), (0, 0, 1), (0, 0, -1), (0, 1, 0), (0, 1, 1), (0, 1, -1), (0, -1, 0), (0, -1, 1), (0, -1, -1), (1, 0, 0), (1, 0, 1), (1, 0, -1), (1, 1, 0), (1, 1, 1), (1, 1, -1), (1, -1, 0), (1, -1, 1), (1, -1, -1), (-1, 0, 0), (-1, 0, 1), (-1, 0, -1), (-1, 1, 0), (-1, 1, 1), (-1, 1, -1), (-1, -1, 0), (-1, -1, 1), (-1, -1, -1)]
这将返回:
[[(0, 0, 0),
(0, 0, 1),
(0, 1, 0),
(0, 1, 1),
(1, 0, 0),
(1, 0, 1),
(1, 1, 0),
(1, 1, 1)],
[(0, 0, 0),
(0, 0, -1),
(0, 1, 0),
(0, 1, -1),
(1, 0, 0),
(1, 0, -1),
(1, 1, 0),
(1, 1, -1)],
[(0, 0, 0),
(0, 0, 1),
(0, -1, 0),
(0, -1, 1),
(1, 0, 0),
(1, 0, 1),
(1, -1, 0),
(1, -1, 1)],
[(0, 0, 0),
(0, 0, -1),
(0, -1, 0),
(0, -1, -1),
(1, 0, 0),
(1, 0, -1),
(1, -1, 0),
(1, -1, -1)],
[(0, 0, 0),
(0, 0, 1),
(0, 1, 0),
(0, 1, 1),
(-1, 0, 0),
(-1, 0, 1),
(-1, 1, 0),
(-1, 1, 1)],
[(0, 0, 0),
(0, 0, -1),
(0, 1, 0),
(0, 1, -1),
(-1, 0, 0),
(-1, 0, -1),
(-1, 1, 0),
(-1, 1, -1)],
[(0, 0, 0),
(0, 0, 1),
(0, -1, 0),
(0, -1, 1),
(-1, 0, 0),
(-1, 0, 1),
(-1, -1, 0),
(-1, -1, 1)],
[(0, 0, 0),
(0, 0, -1),
(0, -1, 0),
(0, -1, -1),
(-1, 0, 0),
(-1, 0, -1),
(-1, -1, 0),
(-1, -1, -1)]]