1

I have a list with nested sub-list with the following structure

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']
   ]
]

I am trying to collect all data in in_data and make a unique list that contains sub-lists, one for all the "headers"/ names and one for each item + values in the correct order. So the information is preserved but in a different data-structure.

I want to achieve this list:

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

I am trying to do it in the most pythonic way. I tried with for loops and also map() + lambda but no succeess.

would be the easy way?

4
  • 3
    . I tried with for loops and also map() + lambda - you need to post those attempts Commented Nov 10, 2019 at 16:03
  • 1
    What's with the name vs. Skill elements? The most Pythonic way would probably be using list comprehensions. Commented Nov 10, 2019 at 16:16
  • 1
    why 'Skill' word should be skipped/ignored? Commented Nov 10, 2019 at 16:22
  • 2
    i'd recommend rethinking this structure. dictionaries seem to make much more sense here. Commented Nov 10, 2019 at 16:24

2 Answers 2

2

The optimized approach (powered by composite dict keys (<skill name>, <column name>) and dict.get method):

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)

The output:

[['names', 'name_1', 'name_2', 'name_3'],
 ['item_C', '3', '-', '7'],
 ['item_D', '4', '-', '-'],
 ['item_B', '2', '5', '6'],
 ['item_A', '-', '2', '-']]
Sign up to request clarification or add additional context in comments.

1 Comment

@PM2Ring, that's Ok
1

You can use 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()]]

Output:

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.