我希望输入一个n * m数组,结果输出是一个包含行元素不同组合的数组。 这是一个要澄清的示例(尽管是非常简单的情况):
我希望输入以下形状的数组:
[[1, 2, 3]
[2, 5, 6]]
并希望收到以下输出:
[[1,2], [1,5], [1,6], [2,5], [2,6], [3,2], [3,5], [3,6]]
如您所见,由于重复,不包括[2,2]
。
当输入维事先已知时,我可以编写包含嵌套的for循环的快速而肮脏的代码:
A = [[1, 2, 3], [2, 5, 6]]
m = len(A[0])
for i in range(0, m):
for j in range(0, m):
if A[0][i]!=A[1][j]: #check and eliminate repetition
combined.append([A[0][i],A[1][j])
choice_num.append([i+1, j+1]) #See (**) below
我真的很想知道如何将其实现为递归函数,因此给定一些输入n-D数组A,可以简单地将其称为:
recursive_looper(A)
(**)我想要的另一个功能是该函数输出与组合中使用的元素对应的列号,因此我们得到两个输出:
element values: [[1,2], [1,5], [1,6], [2,5], [2,6], [3,2], [3,5], [3,6]]
element position: [[1,1], [1,2], [1,3], [2,2], [2,3], [3,1], [3,2], [3,3]]
任何提示或建议将不胜感激!
编辑:我对可以实现所需输出的任何解决方案持开放态度。递归只是想到的第一件事。
编辑2(扩展功能):此代码不得限于特定的列表输入形状,而可以扩展为任何形状(n,m)的数组。 我将提供代码崩溃的示例。解决方法是实现n-1个条件语句,我想避免,因为必须先验知道数组形状。
A = [[2, 4, 1, 11, 3], [3, 2, 1, 4, 11], [2, 3, 4, 17, 13]]
如果我不对您的索引编制/过滤器进行任何修改,则会收到“过滤”列表的以下输出:
#[[2, 3, 2], [2, 3, 3], [2, 3, 4], [2, 3, 17], [2, 3, 13], [2, 1, 2], ..., [3, 11, 13]]
我立即注意到它只比较元素位置0和位置1的“相似性”,因此为什么第一个组合包含两个2。 我可以对索引采集器和过滤器循环进行如下修改:
for i in range(0, len(projects_master)-2):
indexes = [idx for idx, t in enumerate(prod) if t[i] == t[i+1] or t[i]==t[i+2] or t[i+1] == t[i+2] ]
res = []
for i in range(0, len(A)-2):
res.append(list(filter( lambda v: v[i] != v[i+1] and v[i] != v[i+2] and v[i+1] != v[i+2], prod)))
result = [list(t) for t in res[0]]
这确实给出正确的输出,但是就像我说的,我需要写出n-1个t [i]和v [i]条件。如何自动完成?
编辑3-最终 多亏了那些提供不同方法来帮助我实现相同最终目标的人。我从每个人那里获得了一些见识,并写了一些对我来说有意义的东西,并且似乎对任何输入都起作用。过滤重复项并将其从组合中删除的代码如下所示:
ind_remove = []
for i in range(0, len(prod)):
if len(prod[i]) != len(set(prod[i])):
ind_remove.append(i)
adder=0
for i in ind_remove:
del prod[i-adder]
adder=adder+1 #takes into account change in indices after an element is deleted.
答案 0 :(得分:0)
您可以使用itertools.product生成所需的组合,其作用类似于两组之间的笛卡尔乘积以生成组合。
因此,如果列表为[[1, 2], [3, 4]]
,则子列表中的笛卡尔乘积将为
[[1, 3], [1, 4], [2, 3], [2, 4]]
from itertools import product
a = [[1, 2, 3], [2, 5, 6]]
# Generate all possible products, *a gives you two lists
prod = list(product(*a))
#[(1, 2), (1, 5), (1, 6), (2, 2), (2, 5), (2, 6), (3, 2), (3, 5), (3, 6)]
#Get the list of duplicate indexes
indexes = [idx for idx, t in enumerate(prod) if t[0] == t[1] ]
print(indexes)
#[3]
#Remove tuples who are duplicates
res = list(filter( lambda v: v[0] != v[1], prod))
print(res)
#[(1, 2), (1, 5), (1, 6), (2, 5), (2, 6), (3, 2), (3, 5), (3, 6)]
#Convert the tuples to list
result = [list(t) for t in res]
print(result)
#[[1, 2], [1, 5], [1, 6], [2, 5], [2, 6], [3, 2], [3, 5], [3, 6]]
答案 1 :(得分:0)
您可以使用一个函数来迭代给定列表列表的第一个列表的项目,并将每个项目与递归调用中的组合合并:
def nonrepetitive_product(lists):
if not lists:
yield []
return
first, *rest = lists
combinations = list(nonrepetitive_product(rest))
for item in first:
for combination in combinations:
if item not in combination:
yield [item, *combination]
所以给定:
l = [[1, 2, 3], [2, 5, 6]]
list(nonrepetitive_product(l))
返回:
[[1, 2], [1, 5], [1, 6], [2, 5], [2, 6], [3, 2], [3, 5], [3, 6]]
答案 2 :(得分:0)
如果您想要任意数量的行的位置和值,最好结合使用itertools.product
和enumerate
。过滤有些棘手,但是可以做到:
import itertools
A = [[1, 2, 3], [2, 5, 6], [7, 8, 3]]
prod = itertools.product(*map(enumerate, A)) # yields ((i,x),(j,y),(k,z),...) nested tuples
transposed = ([*zip(*pairs)] for pairs in prod) # yields ((i,j,k,...), (x,y,z,...)) 2-tuples
filtered = [(ijk, xyz) for ijk, xyz in transposed if len(xyz) == len(set(xyz))] # filter dupes
indexes, values = zip(*filtered) # you might find `filtered` more useful than separate lists