如果有人问过这个问题,我可能没有必要的词汇来找到正确的问题。
如果我有这样的等长列表(或元组):
[6, 4, 7] [gold, blue, red] [dog, cat, echidna] [hot, cold, rainy]
一组键,它们是已知范围内的连续整数,等于唯一组合的数量(在本例中为81)。
是否可以从每个列表中为每个键选择一个项目,以确保组合是唯一的? (并从组合中获取密钥)。
这样
0可能会产生(6,金,猫,热)
1可能会产生(猫,4,金,雨)
2可能会产生(热,红,针鼹,7)
等...
并且知道(热,红,针鼹,7)是2?
产生的选择假设已知并修复了列表的长度和顺序,列表中的项目保证在每个列表和所有列表中是唯一的,并且每个列表都可以排序/排序
答案 0 :(得分:1)
如果输入值在不同列表中都是唯一的,那么您可以。减少元素以减少输出
import itertools
input = [[6, 4], ['gold', 'blue'], ['dog', 'cat'], ['hot', 'cold']];
output = list(itertools.product(*input))
print output
所以list[0] -> (6, 'gold', 'dog', 'hot')
<强>输出强>
[(6, 'gold', 'dog', 'hot'), (6, 'gold', 'dog', 'cold'), (6, 'gold', 'cat', 'hot'), (6, 'gold', 'cat', 'cold'),
(6, 'blue', 'dog', 'hot'), (6, 'blue', 'dog', 'cold'), (6, 'blue', 'cat', 'hot'), (6, 'blue', 'cat', 'cold'),
(4, 'gold', 'dog', 'hot'), (4, 'gold', 'dog', 'cold'), (4, 'gold', 'cat', 'hot'), (4, 'gold', 'cat', 'cold'),
(4, 'blue', 'dog', 'hot'), (4, 'blue', 'dog', 'cold'), (4, 'blue', 'cat', 'hot'), (4, 'blue', 'cat', 'cold')]
然后使用itertools.groupby
import itertools
input = [[1, 2], [1, 2], [1, 2], [1, 2]];
output = [k for k,_ in list(itertools.groupby(itertools.product(*input)))]
print output
<强>输出强>
[[1, 1, 1, 1], [1, 1, 1, 2], [1, 1, 2, 2], [1, 1, 1, 2], [1, 1, 2, 2], [1, 2, 2, 2],
[1, 1, 1, 2], [1, 1, 2, 2], [1, 2, 2, 2], [1, 1, 2, 2], [1, 2, 2, 2], [2, 2, 2, 2]]
使用数字= 1000的示例timeit
0.00650215148926 (without group by)
0.02952003479 (with group by)
0.0323181152344 (algorithm from @GarrettR)
答案 1 :(得分:0)
这样的事可能有用。认为它并不认为你有一个键列表。相反,它通过枚举列表的产品来动态生成密钥。
a,b,c,d = [6, 4, 7], ['gold', 'blue', 'red'], ['dog', 'cat', 'echidna'], ['hot', 'cold', 'rainy']
from itertools import product
forward = {}
backward = {}
for i,thing in enumerate(product(a,b,c,d)):
forward[i] = thing
backward[thing] = i
77 -> (7, 'red', 'cat', 'rainy')
78 -> (7, 'red', 'echidna', 'hot')
79 -> (7, 'red', 'echidna', 'cold')
答案 2 :(得分:0)
您可以使用公式构建有效的映射,而无需实现数据结构。假设我们反复采用n mod每个序列的长度并除以长度。这给了我们:
def get_nth(seqs, n):
out = []
for seq in seqs:
i = n % len(seq)
n //= len(seq)
out.append(seq[i])
return out
之后我们
>>> seqs = [[6, 4, 7], ['gold', 'blue', 'red'],
['dog', 'cat', 'echidna'], ['hot', 'cold', 'rainy']]
>>> get_nth(seqs, 0)
[6, 'gold', 'dog', 'hot']
>>> get_nth(seqs, 1)
[4, 'gold', 'dog', 'hot']
>>> get_nth(seqs, 80)
[7, 'red', 'echidna', 'rainy']
>>> len(set(tuple(get_nth(seqs, i)) for i in range(81)))
81
即使在很长的名单上,这也会很快发挥作用:
>>> seqs = [list(range(10**3))]*10**3
>>> %timeit get_nth(seqs, 0)
1000 loops, best of 3: 592 µs per loop
>>> %timeit get_nth(seqs, (10**3)**(10**3)-1)
100 loops, best of 3: 11.2 ms per loop
>>> get_nth(seqs, (10**3)**(10**3)-1)[:10]
[999, 999, 999, 999, 999, 999, 999, 999, 999, 999]