繁体   English   中英

从列表中创建具有多个变体的所有可能组合

[英]create all possible combinations with multiple variants from list

好的,所以问题如下:

假设我有一个像这样的列表[12R,102A,102L,250L]我想要的是所有可能组合的列表,但是只有一个组合/数字。 所以对于上面的例子,我想要的 output 是:

[12R,102A,250L]
[12R,102L,250L]

我的实际问题要复杂得多,还有更多站点。 谢谢你的帮助

编辑:在阅读了一些评论后,我想这有点不清楚。 我在这里有 3 个唯一数字,[12、102 和 250],对于某些数字,我有不同的变体,例如 [102A、102L]。 我需要的是一种方法来组合不同的位置[12,102,250] 和所有可能的变化。 就像我在上面介绍的列表一样。 它们是唯一有效的解决方案。 [12R] 不是。 [12R,102A,102L,250L] 也不是。 到目前为止,我已经用嵌套循环做到了这一点,但是这些数字中有很多变化,所以我不能再这样做了

生病再次编辑:好的,所以似乎仍然存在一些混乱,所以我可能会扩展我之前提出的观点。 我正在处理的是DNA。 12R 表示序列中的第 12 个 position 更改为 R。 所以解[12R,102A,250L]表示position 12上的氨基酸是R,102是A 250是L。

这就是为什么像 [102L, 102R, 250L] 这样的解决方案不可用的原因,因为同一个 position 不能被 2 个不同的氨基酸占据。

谢谢你

所以它适用于["10A","100B","12C","100R"] (案例 1)和['12R','102A','102L','250L'] (案例 2)

import itertools as it

liste = ['12R','102A','102L','250L']

comb = []
for e in it.combinations(range(4), 3):
    e1 = liste[e[0]][:-1]
    e2 = liste[e[1]][:-1]
    e3 = liste[e[2]][:-1]
    if e1 != e2 and e2 != e3 and e3 != e1:
        comb.append([e1+liste[e[0]][-1], e2+liste[e[1]][-1], e3+liste[e[2]][-1]])
print(list(comb))
# case 1 : [['10A', '100B', '12C'], ['10A', '12C', '100R']]
# case 2 : [['12R', '102A', '250L'], ['12R', '102L', '250L']]

尝试这个:

from itertools import groupby
import re

def __genComb(arr, res=[]):
    for i in range(len(res), len(arr)):
        el=arr[i]
        if(len(el[1])==1):
            res+=el[1]
        else:
            for el_2 in el[1]:
                yield from __genComb(arr, res+[el_2])
            break
    if(len(res)==len(arr)): yield res

def genComb(arr):
    res=[(k, list(v)) for k,v in groupby(sorted(arr), key=lambda x: re.match(r"(\d*)", x).group(1))]
    yield from __genComb(res)

示例 output(使用您提供的输入):

test=["12R","102A","102L","250L"]

for el in genComb(test):
    print(el)

# returns:

['102A', '12R', '250L']
['102L', '12R', '250L']

您可以使用递归生成器 function:

from itertools import groupby as gb
import re

def combos(d, c = []):
  if not d:
     yield c
  else:
     for a, b in d[0]:
       yield from combos(d[1:], c + [a+b]) 

d = ['12R', '102A', '102L', '250L']
vals = [re.findall('^\d+|\w+$', i) for i in d]
new_d = [list(b) for _, b in gb(sorted(vals, key=lambda x:x[0]), key=lambda x:x[0])]
print(list(combos(new_d)))

Output:

[['102A', '12R', '250L'], ['102L', '12R', '250L']]
import re

def get_grouped_options(input):
     options = {}
     for option in input:
          m = re.match('([\d]+)([A-Z])$', option)
          if m:
               position = int(m.group(1))
               acid = m.group(2)
          else:
               continue
          if position not in options:
               options[position] = []
          options[position].append(acid)
     return options


def yield_all_combos(options):
     n = len(options)
     positions = list(options.keys())
     indices = [0] * n
     while True:
          yield ["{}{}".format(position, options[position][indices[i]])
                 for i, position in enumerate(positions)]
          j = 0
          indices[j] += 1
          while indices[j] == len(options[positions[j]]):
               # carry
               indices[j] = 0
               j += 1
               if j == n:
                    # overflow
                    return
               indices[j] += 1


input = ['12R', '102A', '102L', '250L']

options = get_grouped_options(input)

for combo in yield_all_combos(options):
     print("[{}]".format(",".join(combo)))

给出:

[12R,102A,250L]
[12R,102L,250L]

我相信这就是你要找的!

这通过

  • 生成每个前缀可以具有的所有后缀的集合
  • 查找位置总数(将每个子列表的长度相乘)
  • 通过基于集合中其成员后缀 position 的读取索引和绝对结果索引(最终结果中的已知位置)来旋转每个后缀
import collections
import functools
import operator
import re

# initial input
starting_values = ["12R","102A","102L","250L"]

d = collections.defaultdict(list)  # use a set if duplicates are possible
for value in starting_values:
    numeric, postfix = re.match(r"(\d+)(.*)", value).groups()
    d[numeric].append(postfix)  # .* matches ""; consider (postfix or "_") to give value a size

# d is now a dictionary of lists where each key is the prefix
# and each value is a list of possible postfixes


# each set of postfixes multiplies the total combinations by its length
total_combinations = functools.reduce(
    operator.mul,
    (len(sublist) for sublist in d.values())
)

results = collections.defaultdict(list)
for results_pos in range(total_combinations):
    for index, (prefix, postfix_set) in enumerate(d.items()):
        results[results_pos].append(
            "{}{}".format(  # recombine the values
                prefix,     # numeric prefix
                postfix_set[(results_pos + index) % len(postfix_set)]
            ))

# results is now a dictionary mapping { result index: unique list }

显示

# set width of column by longest prefix string
# need a collection for intermediate cols, but beyond scope of Q
col_width = max(len(str(k)) for k in results)
for k, v in results.items():
    print("{:<{w}}: {}".format(k, v, w=col_width))


0: ['12R', '102L', '250L']
1: ['12R', '102A', '250L']

具有更高级的输入

["12R","102A","102L","250L","1234","1234A","1234C"]

0: ['12R', '102L', '250L', '1234']
1: ['12R', '102A', '250L', '1234A']
2: ['12R', '102L', '250L', '1234C']
3: ['12R', '102A', '250L', '1234']
4: ['12R', '102L', '250L', '1234A']
5: ['12R', '102A', '250L', '1234C']

您可以通过一set确认这些值确实是唯一的

final = set(",".join(x) for x in results.values())
for f in final:
    print(f)

12R,102L,250L,1234
12R,102A,250L,1234A
12R,102L,250L,1234C
12R,102A,250L,1234
12R,102L,250L,1234A
12R,102A,250L,1234C

笔记

暂无
暂无

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

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