1

I have a list of lists, where the first list is a 'header' list and the rest are data lists. Each of these 'sub' lists are the same size, as shown below:

list1 = [
    ["Sno", "Name", "Age", "Spirit", "Status"],
    [1, "Rome", 43, "Gemini", None],
    [2, "Legolas", 92, "Libra", None]
]

I want to merge all of these 'sub' lists into one dictionary, using that first 'sub' list as a header row that maps each value in the row to a corresponding value in subsequent rows.

This is how my output should look:

result_dict = {
    1: {"Name": "Rome", "Age": 43, "Spirit": "Gemini", "Status": None},
    2: {"Name": "Legolas", "Age": 92, "Spirit": "Libra", "Status": None}
}

As you can see, 1, 2, etc. are unique row numbers (they correspond to the Sno column in the header list).


So far, I am able to get every second element as the key using this code:

list1_as_dict= {p[0]:p[1:] for p in list1}

print(list1_as_dict)

Which outputs:

{
    'Sno': ['Name', 'Age', 'Spirit', 'Status'],
    1: ['Rome', 43, 'Gemini', None],
    2: ['Legolas', 92, 'Libra', None]
}

But I don't know how make each of the data 'sub' lists a dictionary mapped to the corresponding headers.

How can I get my desired output?

Henry Ecker
  • 34,399
  • 18
  • 41
  • 57
Zenith_1024
  • 231
  • 2
  • 14
  • 8
    This question is being [discussed on meta](https://meta.stackoverflow.com/questions/418708). – cigien Jun 15 '22 at 01:18

3 Answers3

7

Something like

spam = [["Sno","Name","Age","Spirit","Status"],[1, "Rome", 43,"Gemini",None],[2,"Legolas", 92, "Libra",None]]
keys = spam[0][1:] # get the keys from first sub-list, excluding element at index 0

# use dict comprehension to create the desired result by iterating over
# sub-lists, unpacking sno and rest of the values
# zip keys and values and create a dict and sno:dict pair respectively
result = {sno:dict(zip(keys, values)) for sno, *values in spam[1:]}
print(result)

output

{1: {'Name': 'Rome', 'Age': 43, 'Spirit': 'Gemini', 'Status': None}, 2: {'Name': 'Legolas', 'Age': 92, 'Spirit': 'Libra', 'Status': None}}
buran
  • 13,682
  • 10
  • 36
  • 61
  • how do I it if i want age to be the primary key. – Zenith_1024 Jun 14 '22 at 19:10
  • @buran I tried this, keys = [spam[0][0],spam[0][1],spam[0][3], spam[0][4]] . It prints the same exact thing that your code is printing. Wondering what i am missing – Zenith_1024 Jun 14 '22 at 19:17
  • 2
    In this case it looks the keys will be OK, however you will need to properly construct the `values` Note that `age` may NOT be unique, while `sno` is (according to you) – buran Jun 14 '22 at 19:31
1

I'm sure you'd love Pandas. There is a bit of learning curve, but it offers a lot in exchange - most of operations over this dataset can be done in a single line of code.

import pandas as pd
pd.DataFrame(list1[1:], columns=list1[0]).set_index('Sno')

Output:

        Name  Age  Spirit Status
Sno                             
1       Rome   43  Gemini   None
2    Legolas   92   Libra   None
Marat
  • 15,215
  • 2
  • 39
  • 48
  • Agreed. I'd use pandas for this. Specially, if there are a lot of them to build. – MYousefi Jun 14 '22 at 19:01
  • This can be done in one step with [from_records](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.from_records.html#pandas-dataframe-from-records) `df = pd.DataFrame.from_records(list1[1:], columns=list1[0], index='Sno')`. Related pandas specific Q & A here [Creating a Pandas DataFrame from a Numpy array: How do I specify the index column and column headers?](/q/20763012/15497888) – Henry Ecker Jun 14 '22 at 23:25
-1
my_dict = {p[0]: dict((x,y) for x, y in zip(list1[0][1:], p[1:])) for p in list1[1:]}
print(my_dict)

Results in:

{1: {'Name': 'Rome', 'Age': 43, 'Spirit': 'Gemini', 'Status': None}, 2: {'Name': 'Legolas', 'Age': 92, 'Spirit': 'Libra', 'Status': None}}
MYousefi
  • 978
  • 1
  • 5
  • 10
  • this is buran's answer with an unnecessary extra loop. Your inner loop is syntactically like the following: `[x for x in y]` especially since zip already returns a tuple for every next call – Jab Jun 14 '22 at 19:01
  • You are correct. I just didn't notice that answer when I posted. – MYousefi Jun 14 '22 at 19:04
  • No worries, I had the same issue. – Jab Jun 14 '22 at 19:05