首页 > 解决方案 > 如何聚合嵌套列表中的元素

问题描述

我有一个列表如下:

original_list = [['B_S', 'O', 'O', 'O'],
                 ['B_S', 'O', 'O', 'O'],
                 ['O', 'O', 'B_S', 'O'],

                 ['O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'O', 'O', 'O'],
                 ['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'O', 'O'],
                 ['O', 'O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'O'],

                 ['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'B_S', 'O', 'O'],
                 ['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'O', 'O', 'O'],
                 ['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'O', 'O', 'O']]

我想根据大多数元素将每三个列表聚合为一个列表。也就是说,如果两个位置具有相同的元素,则新列表将采用相同位置的相同元素。所需的输出应如下所示:

desired_output = [['B_S', 'O', 'O', 'O'],
                 ['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O'],
                 ['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'O', 'O', 'O']]

我试过这个复杂的功能:

def collect_labels(lab_user):

  def aggregate_labels(a,b,c):
     aggregated_list = []
     # iterate over 3 lists
     for x,y,z in zip(a, b, c):
        if x != 'O':
          aggregated_list.append(x)
        elif y != 'O':
          aggregated_list.append(y)
        #elif z != 'O':
          #aggregated_list.append(z)  # you can improve the code
        else:
          aggregated_list.append(z)
     return aggregated_list

  result = [aggregate_labels(lab_user[i], lab_user[i+1], lab_user[i+2]) for i in range(0,len(lab_user)-2, 3)] 
  return result

但它返回错误的结果:

wrong_result= [['B_S', 'O', 'O', 'O'],
               ['O', 'O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'O'],
               ['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'B_S', 'O', 'O']]

如果您能帮助我更正我的代码,我将不胜感激!

标签: pythonlistfunction

解决方案


问题中最难的部分只是将您的列表分为三个块:

>>> [original_list[i*3:i*3+3] for i in range(len(original_list)//3)]
[[['B_S', 'O', 'O', 'O'], ['B_S', 'O', 'O', 'O'], ['O', 'O', 'B_S', 'O']], 
[['O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'O', 'O', 'O'], ['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'O', 'O'], ['O', 'O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'O']], 
[['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'B_S', 'O', 'O'], ['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'O', 'O', 'O'], ['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'O', 'O', 'O']]]

但是,一旦有了它,您就可以使用zip对要比较的项目进行分组:

>>> chunks = [original_list[i*3:i*3+3] for i in range(len(original_list)//3)]
>>> [list(zip(*j)) for j in chunks]
[[('B_S', 'B_S', 'O'), ('O', 'O', 'O'), ('O', 'O', 'B_S'), ('O', 'O', 'O')],
[('O', 'O', 'O'), ('O', 'O', 'O'), ('O', 'O', 'O'), ('O', 'O', 'O'), ('B_S', 'O', 'O'), ('O', 'B_S', 'O'), ('O', 'O', 'B_S'), ('O', 'O', 'O'), ('O', 'O', 'O'), ('O', 'O', 'O')], 
[('O', 'O', 'O'), ('O', 'O', 'O'), ('O', 'O', 'O'), ('O', 'O', 'O'), ('O', 'O', 'O'), ('B_S', 'B_S', 'B_S'), ('O', 'O', 'O'), ('O', 'O', 'O'), ('B_S', 'B_S', 'B_S'), ('B_S', 'O', 'O'), ('O', 'O', 'O'), ('O', 'O', 'O')]]

然后您只想在每个出现频率最高的压缩元组中选择项目——也就是statistics.mode

>>> import statistics
>>> [[statistics.mode(i) for i in zip(*j)] for j in chunks]
[['B_S', 'O', 'O', 'O'], 
['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O'], 
['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'O', 'O', 'O']]

或一起:

from statistics import mode

original_list = [['B_S', 'O', 'O', 'O'],
                 ['B_S', 'O', 'O', 'O'],
                 ['O', 'O', 'B_S', 'O'],

                 ['O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'O', 'O', 'O'],
                 ['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'O', 'O'],
                 ['O', 'O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'O'],

                 ['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'B_S', 'O', 'O'],
                 ['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'O', 'O', 'O'],
                 ['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'O', 'O', 'O']]
CHUNK_LEN = 3

desired_output = [
    [mode(i) for i in zip(*j)] 
    for j in (
        original_list[i*CHUNK_LEN:(i+1)*CHUNK_LEN] 
        for i in range(len(original_list)//CHUNK_LEN)
    )
]

显然,如果您可以在original_list前面正确分组,那就容易多了:

from statistics import mode

original_list = [[['B_S', 'O', 'O', 'O'],
                 ['B_S', 'O', 'O', 'O'],
                 ['O', 'O', 'B_S', 'O']],

                 [['O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'O', 'O', 'O'],
                 ['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'O', 'O'],
                 ['O', 'O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'O']],

                 [['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'B_S', 'O', 'O'],
                 ['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'O', 'O', 'O'],
                 ['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'O', 'O', 'O']]]

desired_output = [
    [mode(i) for i in zip(*j)] 
    for j in original_list
]

推荐阅读