我在python中有这样的元组数组:
[(1,2),(2,3),(2,4),(2,5),(2,6),(3,1),(3,2),(3,4)]
我需要生成给定长度的所有组合,但是要有一定条件,元组中总是只有两个相同的数字。
对于此示例,在开始生成组合时,我需要先添加(1,2)
然后再添加(2,3)
,但是之后我不能添加(2,4)
,因为数字2
已经使用了2次在[(1,2),(2,3)]
中,因此我需要跳过或删除起始数组以下项(包含数字2):(2,4),(2,5),(2,6),(3,2)
,然后继续进行生成。给定长度3的第一个组合为[(1,2),(2,3),(3,1)]
,第二个为[(1,2),(2,3),(3,4)]
,然后为[(1,2),(2,4),(3,1)]
,依此类推。
有人可以帮我怎么做吗?
答案 0 :(得分:1)
您可以将递归与生成器一起使用:
from collections import Counter
def groups(d, l, c = []):
if l == len(c):
yield c
else:
for i in d:
if i not in c:
_c = Counter([j for k in [*c, i] for j in k])
if all(j < 3 for j in _c.values()):
yield from groups(d, l, c+[i])
data = [(1,2),(2,3),(2,4),(2,5),(2,6),(3,1),(3,2),(3,4)]
result = list(groups(data, 3))
final_result = [a for i, a in enumerate(result) if all(any(c not in h for c in a) for h in result[:i])]
输出:
[[(1, 2), (2, 3), (3, 1)], [(1, 2), (2, 3), (3, 4)], [(1, 2), (2, 4), (3, 1)], [(1, 2), (2, 4), (3, 4)], [(1, 2), (2, 5), (3, 1)], [(1, 2), (2, 5), (3, 4)], [(1, 2), (2, 6), (3, 1)], [(1, 2), (2, 6), (3, 4)], [(1, 2), (3, 1), (3, 2)], [(1, 2), (3, 1), (3, 4)], [(1, 2), (3, 2), (3, 4)], [(2, 3), (2, 4), (3, 1)], [(2, 3), (2, 4), (3, 4)], [(2, 3), (2, 5), (3, 1)], [(2, 3), (2, 5), (3, 4)], [(2, 3), (2, 6), (3, 1)], [(2, 3), (2, 6), (3, 4)], [(2, 4), (2, 5), (3, 1)], [(2, 4), (2, 5), (3, 4)], [(2, 4), (2, 6), (3, 1)], [(2, 4), (2, 6), (3, 4)], [(2, 4), (3, 1), (3, 2)], [(2, 4), (3, 1), (3, 4)], [(2, 4), (3, 2), (3, 4)], [(2, 5), (2, 6), (3, 1)], [(2, 5), (2, 6), (3, 4)], [(2, 5), (3, 1), (3, 2)], [(2, 5), (3, 1), (3, 4)], [(2, 5), (3, 2), (3, 4)], [(2, 6), (3, 1), (3, 2)], [(2, 6), (3, 1), (3, 4)], [(2, 6), (3, 2), (3, 4)]]
答案 1 :(得分:0)
from random import sample
# Define variables
# All possible elements
all_elements = [1,2,3,4,5,6,7]
# Current possible free elements
possible_elements = {e: 0 for e in all_elements}
# Max number of element usage
MAX = 2
# Result length
N = 5
# Tuple length
L = 2
# Result
result = []
for _ in range(N):
# Check if we can't construct a new tuple
try:
# Randomly get free elements
t = sample(possible_elements.keys(), L)
except ValueError:
break
# Add tuple to result
result.append(t)
# Check elements
for element in t:
# List for delete non-free elements
elements_to_delete = []
# Check if we can't use the element (it is filled to MAX)
possible_elements[element] += 1
if possible_elements[element] == MAX:
# If yes, add it to to-delete list
elements_to_delete.append(element)
# Delete all non-free elements
for e in elements_to_delete:
del possible_elements[e]
result
返回:
[[1, 6], [6, 4], [3, 5], [1, 3], [7, 5]]
答案 2 :(得分:0)
有几种方法可以做到这一点(大多数方法效率更高),但是只要您的原始元组数组很短,我认为您应该坚持概念上最简单的方法。那可能是在3个for循环中创建所有置换(从元组数组中获取i,j,k)(使用if条件检查i,j和k是否不相同)并将其存储在字典中(键可能是数组中用_分隔的索引)。 最后,您检查字典中是否有任何禁止的组合(使用了2个...)并将其删除。 当然,您也可以将最后两个步骤结合起来,但是如果您原来的阵列要长很多,那会比较慢。
答案 3 :(得分:0)
我首先使用itertools.permutations为元组上长度为3的置换生成一个迭代器。 然后,我通过collections.Counter计算3个元组的子列表中每个元组的所有频率,如果元素的频率超过2,则不将该子列表添加到最终列表中。
string str = "IsRecorded<code>0</code>";
str = str.Replace("<code>0</code>", "");
Console.WriteLine(str);
输出看起来像
import itertools as it
from collections import Counter
li = [(1,2),(2,3),(2,4),(2,5),(2,6),(3,1),(3,2),(3,4)]
perms = []
#Generate all permutations of length 3
for l in it.permutations(li, 3):
flag = True
counters = Counter()
#Iterate through tuple and calculate frequency of each digit via Counter
#Summing up counters for each tuple
for tup in l:
c = Counter(tup)
counters += c
#Iterate through the frequency dict, and if a value is above 2, don't add that tuple
for v in dict(counters).values():
if v > 2:
flag = False
if flag:
perms.append(l)
print(perms)