基于第二层lis的Python非匹配列表

2024-09-29 17:18:44 发布

您现在位置:Python中文网/ 问答频道 /正文

我有两个Python列表:

list_a = [[['Ab'], ['Qr', 'Zr']], [['Gt', 'Mh', 'Nt'], ['Dv', 'Cb']]]
list_b = [['Ab', 'QrB', 'Zr'], ['GtB', 'MhB', 'Nt6B', 'DvB', 'Cb6B5']]

我需要基于list_a取消list_b的展平。我需要:

^{pr2}$

有没有办法得到这个list_c?在

其他信息: 列表的定义应确保:

  • 来自list_a的部分字符串将始终位于list_b中。例如,对于一个列表中的Gt,第二个列表中将有Gt或{}。在
  • 每个列表中的条目不能以不同的顺序排列-即,如果在一个列表中QrZr之前,那么它(Qr或{})必须在第二个列表中的Zr之前。在
  • 每个列表最多可以包含20个字符串。在
  • 每个列表只有唯一的字符串。。例如,Gt在任何列表中不能出现2次或更多次。在

尝试:

以下是我尝试过的:

list_c = [[],[]]
        for ty,iten in enumerate(list_b):
            for q in iten:
                for l_e in list_a:
                    for items in l_e:
                        for t,qr in enumerate(items):
                            if qr in q:
                                list_c[ty].append([q])

其输出为:

[[['Ab'], ['QrB'], ['Zr']], [['GtB'], ['MhB'], ['Nt6B'], ['DbB'], ['Cb6B5']]]

问题是['QrB'], ['Zr']应该组合成{},就像它们在{中组合一样。在

尝试2:

for ty,iten in enumerate(list_b):
    for q in iten:
        for l_e,m in enumerate(list_a):
            for ss,items in enumerate(m):
                for t,qr in enumerate(items):
                    if qr in q:
                        list_a[l_e][ss][t] = q

这样可以工作并产生所需的输出:

[[['Ab'], ['QrB', 'Zr']], [['GtB', 'MhB', 'Nt6B'], ['DvB', 'Cb6B5']]]

但是,它(尝试2)太长了,我想知道:在Python中,这似乎不是正确的方法。有没有一种更像Python的方法?在


Tags: ingt列表forabitemslistqr
3条回答

这是用于任意嵌套深度的递归变量。不太漂亮,但应该有用。在

list_a = [[['Ab'], ['Qr', 'Zr']], [['Gt', 'Mh', 'Nt'], ['Dv', 'Cb']]] 
list_b = [['Ab', 'QrB', 'Zr'], ['GtB', 'MhB', 'Nt6B', 'DvB', 'Cb6B5']]

def flatten(l):
    for el in l:
        if isinstance(el, list):
            for sub in flatten(el):
                yield sub
        else:
            yield el

def flitten(l1, l2, i):
    result = []
    for j in l1:
        if isinstance(j, list):
            i, res = flitten(j, l2, i)
            result.append(res)
        else:
            result.append(l2[i])
            i += 1
    return i, result

def flutten(l1, l2):
    i, result = flitten(l1, list(flatten(l2)), 0)
    return result

print(flutten(list_a, list_b))
# prints [[['Ab'], ['QrB', 'Zr']], [['GtB', 'MhB', 'Nt6B'], ['DvB', 'Cb6B5']]]

考虑到任务相当复杂的性质,您的代码看起来不会太长(在一个列表中查找一个列表,并根据前两个字母将其与另一个列表中的列表进行匹配,然后将原始值替换为保留原始列表嵌套结构的匹配值…)

您至少可以消除一个这样的循环:

for sub_a, sub_b in zip(list_a, list_b):
    for inner_a in sub_a:
        for i, a in enumerate(inner_a):
            for b in sub_b:
                if b.startswith(a):
                    inner_a[i] = b

如果您想要一个更通用的解决方案,它可能会像@Tibor的答案那样涉及递归。在

编辑:给定您提供的额外信息,您可以递归地处理list_a,用基于{}的平坦版本的迭代器将所有短字符串替换为其完整版本。这使用了这样一个事实:字符串在两个列表中以相同的顺序出现,没有重复项。在

^{pr2}$

或者,您可以获取两个列表中每个字符串的索引的扁平化列表,然后循环这些索引:

def flat_indices(L):
    for i, item in enumerate(L):
        if isinstance(item, list):
            for j, inner_list in flat_indices(item):
                yield (j, inner_list) 
        else:
            yield (i, L)

for (a, i), (b, j) in zip(flat_indices(list_a), flat_indices(list_b)):
    a[i] = b[j]

如果您只关心list_a中的子列表的长度,那么可以将list_a转换为其子列表的长度,然后使用它来切片{}的子列表:

# Transform list_a into len of sublists, (generator of generators :)
index_a = ((len(l2) for l2 in l1) for l1 in list_a))  
list_c = []
for flatb, index in zip(list_b, index_a):
    splitb = []
    s = 0
    for i in index:
        splitb.append(flatb[s:s+i])
        s += i
    list_c.append(splitb)

list_c的值:

^{pr2}$

相关问题 更多 >

    热门问题