简体   繁体   English

python - 成对分割列表和唯一元素

[英]python - split a list in pairs and unique elements

I'm having a hard time trying to achieve the following: I have a list (say, [a,b,c,d]) and I need to partition it into pairs and unique elements in every possible way (order is not important), ie: 我正在努力实现以下目标:我有一个列表(比如,[a,b,c,d]),我需要以各种可能的方式将它分成对和唯一元素(顺序并不重要) ),即:

[a,b,c,d], [(a,b), c,d], [(a,b), (c,d)], [a, (b,c), d], [(a,d), (b, c)]...

and so on. 等等。 This thread solves the problem when only pairs are used, but I need also the unique elements and I cannot get it to do it. 当只使用对时, 这个线程解决了这个问题,但是我还需要独特的元素而我无法做到这一点。 Any idea will be much appreciated. 任何想法将不胜感激。 Thanks! 谢谢!

Maybe a simpler solution would be a recursive one. 也许更简单的解决方案是递归的解决方案。 Just create every combination with the first element and move to sublists without it. 只需使用第一个元素创建每个组合,然后移动到没有它的子列表。

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

Given a function that given an even length list, splits it in pairs without taking order into account: 给定一个给出偶数长度列表的函数,将其成对分割而不考虑订单:

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]

we can generate our wanted results: 我们可以生成我们想要的结果:

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

and use like that: 并使用这样的:

for c in gen([1, 2, 3, 4]):
    print c

Output: 输出:

[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)]

Use combinations from itertools : 使用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')]

etc. 等等

Ok! 好! Let's see, this is not the prettiest I could come up with, and I'm pretty sure we could cut a few lines from it, but at least its generic (extracts tuples up to max size), and I wanted to share it with you guys! 让我们看看,这不是我能想到的最漂亮的,而且我很确定我们可以从中删除几行,但至少它是通用的(提取最大大小的元组),我想与之分享你们!

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM