Python 如何对列表中的元素进行嵌套和分组组合?

Python 如何对列表中的元素进行嵌套和分组组合?,python,list,list-comprehension,combinations,permutation,Python,List,List Comprehension,Combinations,Permutation,我希望问题的标题是明确的,如果不是这里有更多的细节 lis_a,lis_b,lis_c=['a','c'],['T','G'],['G','T'] #我正在尝试组合这些列表元素 所有可能的状态=[[x,y,z]表示列表中的x,a表示列表中的y,b表示列表中的z] 打印(“所有可能的状态”) 输出为: all possible states [['A', 'T', 'G'], ['A', 'T', 'T'], ['A', 'G', 'G'], ['A', 'G', 'T'], ['C', 'T

我希望问题的标题是明确的,如果不是这里有更多的细节

lis_a,lis_b,lis_c=['a','c'],['T','G'],['G','T']
#我正在尝试组合这些列表元素
所有可能的状态=[[x,y,z]表示列表中的x,a表示列表中的y,b表示列表中的z]
打印(“所有可能的状态”)

输出为:

all possible states
[['A', 'T', 'G'], ['A', 'T', 'T'], ['A', 'G', 'G'], ['A', 'G', 'T'], ['C', 'T', 'G'], ['C', 'T', 'T'], ['C', 'G', 'G'], ['C', 'G', 'T']]
[[['A', 'T', 'G'], ['C', 'G', 'T']], [['A', 'T', 'T'], ['C', 'G', 'G']], [['A', 'G', 'G'], [['A', 'G', 'T'], ['C', 'T', 'G']]]

Or,

[(['A', 'T', 'G'], ['C', 'G', 'T']), (['A', 'T', 'T'], ['C', 'G', 'G']), (['A', 'G', 'G'], ['C', 'T', 'T']), (['A', 'G', 'T'], ['C', 'T', 'G'])]

我实际上是在尝试以一种方式组合,使两个互补的组合也组合在一起。 i、 e如果从列表A中选择“A”,从列表b中选择“T”,则从列表A中选择“C”,从列表b中选择“G”,这是互补的

我实际上希望所有可能的状态都采用以下格式,其中两个互补状态嵌套在一起:

all possible states
[['A', 'T', 'G'], ['A', 'T', 'T'], ['A', 'G', 'G'], ['A', 'G', 'T'], ['C', 'T', 'G'], ['C', 'T', 'T'], ['C', 'G', 'G'], ['C', 'G', 'T']]
[[['A', 'T', 'G'], ['C', 'G', 'T']], [['A', 'T', 'T'], ['C', 'G', 'G']], [['A', 'G', 'G'], [['A', 'G', 'T'], ['C', 'T', 'G']]]

Or,

[(['A', 'T', 'G'], ['C', 'G', 'T']), (['A', 'T', 'T'], ['C', 'G', 'G']), (['A', 'G', 'G'], ['C', 'T', 'T']), (['A', 'G', 'T'], ['C', 'T', 'G'])]

查看itertools.compositions:

itertools.combinations(iterable, r)
从输入iterable返回元素的r长度子序列


组合按字典排序顺序发出。因此,如果对输入iterable进行了排序,则组合元组将按排序顺序生成。

请查看itertools.combinations:

itertools.combinations(iterable, r)
从输入iterable返回元素的r长度子序列


组合按字典排序顺序发出。因此,如果对输入iterable进行排序,则组合元组将按排序顺序生成。

您可以通过将每个序列规范化为其自身及其补码的最小值来实现这一点。通过取最小值,可以保证序列及其补码都映射到相同的规范化表示

然后你可以按此分组并找到配对。
defaultdict
使分组变得容易

import collections
import itertools

def canonicalize(seq):
    complements = {'A': 'C', 'C': 'A', 'G': 'T', 'T': 'G'}
    comp = tuple(complements[o] for o in seq)
    return min(seq, comp)

grouped = collections.defaultdict(list)
for seq in itertools.product(lis_a, lis_b, lis_c):
    grouped[canonicalize(seq)].append(seq)

list(grouped.values())
# [[('A', 'T', 'G'), ('C', 'G', 'T')],
#  [('A', 'T', 'T'), ('C', 'G', 'G')],
#  [('A', 'G', 'G'), ('C', 'T', 'T')],
#  [('A', 'G', 'T'), ('C', 'T', 'G')]]

您可以通过将每个序列规范化为其自身及其补码的最小值来实现这一点。通过取最小值,可以保证序列及其补码都映射到相同的规范化表示

然后你可以按此分组并找到配对。
defaultdict
使分组变得容易

import collections
import itertools

def canonicalize(seq):
    complements = {'A': 'C', 'C': 'A', 'G': 'T', 'T': 'G'}
    comp = tuple(complements[o] for o in seq)
    return min(seq, comp)

grouped = collections.defaultdict(list)
for seq in itertools.product(lis_a, lis_b, lis_c):
    grouped[canonicalize(seq)].append(seq)

list(grouped.values())
# [[('A', 'T', 'G'), ('C', 'G', 'T')],
#  [('A', 'T', 'T'), ('C', 'G', 'G')],
#  [('A', 'G', 'G'), ('C', 'T', 'T')],
#  [('A', 'G', 'T'), ('C', 'T', 'G')]]

您可以利用列表仅为2元组的事实(从技术上讲,长度为2的列表),并使用二进制XOR
^
到1来获得互补元素

lis_a, lis_b, lis_c = ['A', 'C'], ['T', 'G'], ['G', 'T']

states = []
for i, x in enumerate(lis_a):
    for j, y in enumerate(lis_b):
        for k, z in enumerate(lis_c):
            state = (x, y, z)
            complement = (lis_a[i^1], lis_b[j^1], lis_c[k^1])
            print(state, complement)
            states.append((state, complement))

# As a comprehension:
# states = [((x, y, z), (lis_a[i^1], lis_b[j^1], lis_c[k^1])) for i, x in enumerate(lis_a) for j, y in enumerate(lis_b) for k, z in enumerate(lis_c)]
输出:

('A', 'T', 'G') ('C', 'G', 'T')
('A', 'T', 'T') ('C', 'G', 'G')
('A', 'G', 'G') ('C', 'T', 'T')
('A', 'G', 'T') ('C', 'T', 'G')
('C', 'T', 'G') ('A', 'G', 'T')
('C', 'T', 'T') ('A', 'G', 'G')
('C', 'G', 'G') ('A', 'T', 'T')
('C', 'G', 'T') ('A', 'T', 'G')
('A', 'T', 'G') ('C', 'G', 'T')
('A', 'T', 'T') ('C', 'G', 'G')
('A', 'G', 'G') ('C', 'T', 'T')
('A', 'G', 'T') ('C', 'T', 'G')
如果您想要得到一个没有重复排列的集合(例如,上面输出中的第一行和最后一行),您可以使用以下命令:

lis_a, lis_b, lis_c = ['A', 'C'], ['T', 'G'], ['G', 'T']
states = []
for num in range(4):
    k, j, i = num & 1, (num >> 1) & 1, (num >> 2) & 1  # 000, 001, 010, 011
    state = lis_a[i], lis_b[j], lis_c[k]
    compliment = lis_a[i ^ 1], lis_b[j ^ 1], lis_c[k ^ 1]
    print(state, compliment)
    states.append((state, compliment))
输出:

('A', 'T', 'G') ('C', 'G', 'T')
('A', 'T', 'T') ('C', 'G', 'G')
('A', 'G', 'G') ('C', 'T', 'T')
('A', 'G', 'T') ('C', 'T', 'G')
('C', 'T', 'G') ('A', 'G', 'T')
('C', 'T', 'T') ('A', 'G', 'G')
('C', 'G', 'G') ('A', 'T', 'T')
('C', 'G', 'T') ('A', 'T', 'G')
('A', 'T', 'G') ('C', 'G', 'T')
('A', 'T', 'T') ('C', 'G', 'G')
('A', 'G', 'G') ('C', 'T', 'T')
('A', 'G', 'T') ('C', 'T', 'G')

您可以利用列表仅为2元组的事实(从技术上讲,长度为2的列表),并使用二进制XOR
^
到1来获得互补元素

lis_a, lis_b, lis_c = ['A', 'C'], ['T', 'G'], ['G', 'T']

states = []
for i, x in enumerate(lis_a):
    for j, y in enumerate(lis_b):
        for k, z in enumerate(lis_c):
            state = (x, y, z)
            complement = (lis_a[i^1], lis_b[j^1], lis_c[k^1])
            print(state, complement)
            states.append((state, complement))

# As a comprehension:
# states = [((x, y, z), (lis_a[i^1], lis_b[j^1], lis_c[k^1])) for i, x in enumerate(lis_a) for j, y in enumerate(lis_b) for k, z in enumerate(lis_c)]
输出:

('A', 'T', 'G') ('C', 'G', 'T')
('A', 'T', 'T') ('C', 'G', 'G')
('A', 'G', 'G') ('C', 'T', 'T')
('A', 'G', 'T') ('C', 'T', 'G')
('C', 'T', 'G') ('A', 'G', 'T')
('C', 'T', 'T') ('A', 'G', 'G')
('C', 'G', 'G') ('A', 'T', 'T')
('C', 'G', 'T') ('A', 'T', 'G')
('A', 'T', 'G') ('C', 'G', 'T')
('A', 'T', 'T') ('C', 'G', 'G')
('A', 'G', 'G') ('C', 'T', 'T')
('A', 'G', 'T') ('C', 'T', 'G')
如果您想要得到一个没有重复排列的集合(例如,上面输出中的第一行和最后一行),您可以使用以下命令:

lis_a, lis_b, lis_c = ['A', 'C'], ['T', 'G'], ['G', 'T']
states = []
for num in range(4):
    k, j, i = num & 1, (num >> 1) & 1, (num >> 2) & 1  # 000, 001, 010, 011
    state = lis_a[i], lis_b[j], lis_c[k]
    compliment = lis_a[i ^ 1], lis_b[j ^ 1], lis_c[k ^ 1]
    print(state, compliment)
    states.append((state, compliment))
输出:

('A', 'T', 'G') ('C', 'G', 'T')
('A', 'T', 'T') ('C', 'G', 'G')
('A', 'G', 'G') ('C', 'T', 'T')
('A', 'G', 'T') ('C', 'T', 'G')
('C', 'T', 'G') ('A', 'G', 'T')
('C', 'T', 'T') ('A', 'G', 'G')
('C', 'G', 'G') ('A', 'T', 'T')
('C', 'G', 'T') ('A', 'T', 'G')
('A', 'T', 'G') ('C', 'G', 'T')
('A', 'T', 'T') ('C', 'G', 'G')
('A', 'G', 'G') ('C', 'T', 'T')
('A', 'G', 'T') ('C', 'T', 'G')


在我看来,你想要的只是
列表(itertools.product(lis_a,lis_b,lis_c))
,除非我遗漏了一些东西。你在寻找示例输出显示的所有可能的组合,或者你说的互补组合吗?@DeepSpace:互补序列(或状态)需要嵌套在一起。这是我面临的主要问题。@GrandPhuba:我想要所有可能的组合(这已经是列表理解了),但在所有可能的组合中,我还希望互补状态嵌套在一起。在我看来,你想要的只是
list(itertools.product(lis_a,lis_b,lis_c))
除非我遗漏了什么,否则您是在寻找示例输出中显示的所有可能的组合,还是您所说的互补组合?@DeepSpace:互补序列(或状态)需要嵌套在一起。这是我面临的主要问题。@GrandPhuba:我想要所有可能的组合(这已经是列表理解了),但在所有可能的组合中,我还想要互补状态嵌套在一起。r是什么?请提供更多详细信息。可编辑的是'ACTG',r是3个简单的示例:打印(列表(组合('12345',2))[('1','2'),('1','3'),('1','4'),('1','5'),('2','3'),('2','5'),('3','4'),('3','5'),('4','5'))r是什么?请提供更多细节。iterable是'ACTG',r是3个简单的例子:print(list(组合('12345',2))[('1','2'),('1','3'),('1','4'),('1','5'),('2','3'),('2','5'),('3','4'),('3','5'),('4','5')]FYI Python中的“binary not实际上会给出
-(i+1)
因为数字没有固定的位宽度。你的代码是有效的,但我认为不是你所期望的。试试这些:
~0#-1
~1#-2
。您可能希望
1-i
等介于
0
1
之间。或者你选择的
i^1
:)@mcskinner谢谢你。更新为使用XOR
x^1
n没有问题。我提交了一个列表的编辑以匹配。如果所有的输入列表都保证是成对的互补项,那么这是一个很好的方法。已经编辑过了,但是谢谢@mcskinner。还有一点也不值得注意的是,这个解决方案会产生与OP所需输出相反的副本,但我同时保留答案,因为它只是建立在OP提供的输入之上。@everestial007将我的答案更新为只有唯一的组合。至于
~
a和
^
,它们被称为按位运算符,这意味着它对数字的二进制数字进行运算。有关更多信息,请检查仅供参考,Python中的“binary not”实际上会给出
-(i+1)
,因为数字没有固定的位宽度。你的代码是有效的,但我认为不是你所期望的。试试这些:
~0#-1
~1#-2
。您可能希望
1-i
等介于
0
1
之间。或者你选择的
i^1
:)@mcskinner谢谢你。更新为使用XOR
x^1
n没有问题。我提交了一个列表的编辑以匹配。如果所有的输入列表都保证是成对的补码,那么这是一个很好的方法