python - 成对拆分列表和唯一元素
python - split a list in pairs and unique elements
我很难实现以下目标:
我有一个列表(比如 [a,b,c,d]),我需要以各种可能的方式将它分成对和唯一元素(顺序不重要),即:
[a,b,c,d], [(a,b), c,d], [(a,b), (c,d)], [a, (b,c), d], [(a,d), (b, c)]...
等等。 This thread 解决了仅使用对时的问题,但我还需要独特的元素,但我无法做到这一点。
任何想法将不胜感激。
谢谢!
使用来自itertools的组合:
from itertools import combinations
data = ['a', 'b', 'c', 'd']
pairs = [i for i in combinations(data, 2)]
>>> pairs
[('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'd'), ('c', 'd')]
triplets = [i for i in combinations(data, 3)]
>>> triplets
[('a', 'b', 'c'), ('a', 'b', 'd'), ('a', 'c', 'd'), ('b', 'c', 'd')]
等等
给定一个给定长度为偶数的列表的函数,在不考虑顺序的情况下将其分成两对:
def gen_only_pairs(l):
if not l:
yield []
return
for i in xrange(1, len(l)):
l[1], l[i] = l[i], l[1]
for v in gen_only_pairs(l[2:]):
yield [(l[0], l[1])] + v
l[1], l[i] = l[i], l[1]
我们可以生成我们想要的结果:
from itertools import combinations
def gen(a):
# For all number of pairs
for npairs in xrange(0, len(a) // 2 + 1):
# For each combination of 2 * npairs elements
for c in combinations(a, 2 * npairs):
rest = list(set(a) - set(c))
# Generate all splits of combination into pairs
for v in gen_only_pairs(list(c)):
# Also add the rest of the elements
yield v + rest
然后这样使用:
for c in gen([1, 2, 3, 4]):
print c
输出:
[1, 2, 3, 4]
[(1, 2), 3, 4]
[(1, 3), 2, 4]
[(1, 4), 2, 3]
[(2, 3), 1, 4]
[(2, 4), 1, 3]
[(3, 4), 1, 2]
[(1, 2), (3, 4)]
[(1, 3), (2, 4)]
[(1, 4), (3, 2)]
也许更简单的解决方案是递归解决方案。
只需使用第一个元素创建每个组合,然后在没有它的情况下移动到子列表。
def partition(L):
if len(L) <= 1:
return [L]
partitions = [[L[0]] + p for p in partition(L[1:])]
for i in xrange(1, len(L)):
partitions.extend([[(L[0], L[i])] + p for p in partition(L[1:i]+L[i+1:])])
return partitions
好的!让我们看看,这不是我能想到的最漂亮的,我很确定我们可以从中删减几行,但至少它是通用的(提取最大大小的元组),我想与你们!
from itertools import permutations
thelist = ['a', 'b', 'c', 'd']
def tuplets(l, max):
out = []
for i in permutations(l):
for j in xrange(1, max + 1):
pick(list(i), max, out, [], j, 0)
return out
def pick(l, max, out, branch, num, idx):
if (num == 1):
picked = l[idx]
else:
picked = tuple(l[idx:idx+num])
newBranch = list(branch)
newBranch.append(picked)
if idx + num == len(l):
out.append(newBranch)
return
for i in xrange(1, max + 1):
if idx + i + num > len(l):
continue
pick(l, max, out, newBranch, i, idx + num)
print tuplets(thelist, 2)
我很难实现以下目标: 我有一个列表(比如 [a,b,c,d]),我需要以各种可能的方式将它分成对和唯一元素(顺序不重要),即:
[a,b,c,d], [(a,b), c,d], [(a,b), (c,d)], [a, (b,c), d], [(a,d), (b, c)]...
等等。 This thread 解决了仅使用对时的问题,但我还需要独特的元素,但我无法做到这一点。 任何想法将不胜感激。 谢谢!
使用来自itertools的组合:
from itertools import combinations
data = ['a', 'b', 'c', 'd']
pairs = [i for i in combinations(data, 2)]
>>> pairs
[('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'd'), ('c', 'd')]
triplets = [i for i in combinations(data, 3)]
>>> triplets
[('a', 'b', 'c'), ('a', 'b', 'd'), ('a', 'c', 'd'), ('b', 'c', 'd')]
等等
给定一个给定长度为偶数的列表的函数,在不考虑顺序的情况下将其分成两对:
def gen_only_pairs(l):
if not l:
yield []
return
for i in xrange(1, len(l)):
l[1], l[i] = l[i], l[1]
for v in gen_only_pairs(l[2:]):
yield [(l[0], l[1])] + v
l[1], l[i] = l[i], l[1]
我们可以生成我们想要的结果:
from itertools import combinations
def gen(a):
# For all number of pairs
for npairs in xrange(0, len(a) // 2 + 1):
# For each combination of 2 * npairs elements
for c in combinations(a, 2 * npairs):
rest = list(set(a) - set(c))
# Generate all splits of combination into pairs
for v in gen_only_pairs(list(c)):
# Also add the rest of the elements
yield v + rest
然后这样使用:
for c in gen([1, 2, 3, 4]):
print c
输出:
[1, 2, 3, 4]
[(1, 2), 3, 4]
[(1, 3), 2, 4]
[(1, 4), 2, 3]
[(2, 3), 1, 4]
[(2, 4), 1, 3]
[(3, 4), 1, 2]
[(1, 2), (3, 4)]
[(1, 3), (2, 4)]
[(1, 4), (3, 2)]
也许更简单的解决方案是递归解决方案。 只需使用第一个元素创建每个组合,然后在没有它的情况下移动到子列表。
def partition(L):
if len(L) <= 1:
return [L]
partitions = [[L[0]] + p for p in partition(L[1:])]
for i in xrange(1, len(L)):
partitions.extend([[(L[0], L[i])] + p for p in partition(L[1:i]+L[i+1:])])
return partitions
好的!让我们看看,这不是我能想到的最漂亮的,我很确定我们可以从中删减几行,但至少它是通用的(提取最大大小的元组),我想与你们!
from itertools import permutations
thelist = ['a', 'b', 'c', 'd']
def tuplets(l, max):
out = []
for i in permutations(l):
for j in xrange(1, max + 1):
pick(list(i), max, out, [], j, 0)
return out
def pick(l, max, out, branch, num, idx):
if (num == 1):
picked = l[idx]
else:
picked = tuple(l[idx:idx+num])
newBranch = list(branch)
newBranch.append(picked)
if idx + num == len(l):
out.append(newBranch)
return
for i in xrange(1, max + 1):
if idx + i + num > len(l):
continue
pick(l, max, out, newBranch, i, idx + num)
print tuplets(thelist, 2)