Py学习  »  Python

python-嵌套列表结构中的聚合数据

Lou_Ds • 4 年前 • 648 次点击  

我有一个嵌套子列表的列表,其结构如下

in_data = 
 [
   [
     ['name', 'name_1'],  
     ['item_B', '2'], 
     ['item_C', '3'], 
     ['item_D', '4']
   ],
   [
     ['name', 'name_2'], 
     ['item_B', '5'], 
     ['item_A', '2']
   ],
   [
     ['name', 'name_3'], 
     ['item_B', '6'], 
     ['item_C', '7']
   ]
]

我正在收集所有的数据 in_data 做一个 唯一列表 包含子列表的 “标题” / 姓名 每个项目一个+正确顺序的值。 因此,信息被保存在不同的数据结构中。

我想达到这个目标 :

res_list = 
[
  ['name', ' name_1', ' name_2', 'name_3'], 
  ['item_B', '2', '5', '6'], 
  ['item_C', '3','-', '7'], 
  ['item_D', '4','-', '-'], 
  ['item_A', '-','2', '-'] 
]

我正试着用最恶毒的方式做这件事。我尝试了for循环,也尝试了map()+lambda,但没有成功。

更新

这是我的完整代码。

def get_names(a):
    return reduce(lambda ac, v: ac + [v[0]] if v[0] not in ac else ac, a, [])[1:]


def collect_all_data(_data):
    all_names = set(reduce(lambda x,y: x+y, map(get_names, _data)))
    unique_names = list(map(lambda x: [x], all_names))
    agg = list(map(lambda x:[x], unique_names))
    agg = [['names']] + unique_names
    for team_i, team_data in enumerate(_data):
        team = ""
        for i, skill_val in enumerate(team_data):
            if i==0:
                team = skill_val[1] 
                agg[0].append(team)
                continue
            else :
                 for i_us,us in enumerate(unique_names):
                     if us[0] == skill_val[0]:
                         agg[i_us+1].append(skill_val[1])

    print("\--->{} type:{}".format(agg, type(agg)))
    return agg

collect_all_data(in_data)

它产生输出:

注意 :的 秩序 子列表的 不重要,除非 这个 第一个 ['name', ' name_1', ' name_2', 'name_3'] 这应该是第一次。

  [
    ['names', 'name_1', 'name_2', 'name_3'], 
    ['item_D', '4'], 
    ['item_B', '2', '5', '6'], 
    ['item_C', '3', '7'], 
    ['item_A', '2']
  ]

代码太长,但它没有添加 '-' 当物品没有价值的时候。 会是简单的方法吗?

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/49407
 
648 次点击  
文章 [ 2 ]  |  最新文章 4 年前
RomanPerekhrest
Reply   •   1 楼
RomanPerekhrest    4 年前

优化的方法(由复合dict键提供支持 (<skill name>, <column name>) dict.get 方法):

header = ['names']
names = set()
d = {}

for lst in in_data:
    col_name = lst[0][-1]
    header.append(col_name)
    for name, val in lst[1:]:
        names.add(name)
        d[name, col_name] = val

res = [[n, *[d.get((n, h), '-') for h in header[1:]]] for n in names]
res.insert(0, header)
print(res)

输出:

[['names', 'name_1', 'name_2', 'name_3'],
 ['item_C', '3', '-', '7'],
 ['item_D', '4', '-', '-'],
 ['item_B', '2', '5', '6'],
 ['item_A', '-', '2', '-']]
Ajax1234
Reply   •   2 楼
Ajax1234    4 年前

你可以用 collections.defaultdict :

import collections
in_data = [[['name', 'name_1'], ['item_B', '2'], ['item_C', '3'], ['item_D', '4']], [['Skill', 'name_2'], ['item_B', '5'], ['item_A', '2']], [['Skill', 'name_3'], ['item_B', '6'], ['item_C', '7']]]
d = [list(zip(['name', *b[0][1:]], i)) for b in in_data for i in b[1:]]
new_d = collections.defaultdict(dict)
for i in d:
   new_d[dict(i)['name']][i[-1][0]] = i[-1][-1]

all_names = list({i for b in new_d.values() for i in b})[::-1]
result = [['name', *all_names], *[[a, *[b.get(k, '-') for k in all_names]] for a, b in new_d.items()]]

输出:

[['name', 'name_1', 'name_2', 'name_3'], 
 ['item_B', '2', '5', '6'], 
 ['item_C', '3', '-', '7'], 
 ['item_D', '4', '-', '-'], 
 ['item_A', '-', '2', '-']]