Home > Mobile >  How to create a list of values with the same key from a dictionary
How to create a list of values with the same key from a dictionary

Time:05-11

I have a list of dictionaries similar to the following. The actual data contains arbitrarily many keys, this is just a sample of the data:

l = [{'name': 'jamie', 'age': 26},
     {'name': 'tara', 'age': 43},
     {'name': 'matt', 'age': 34}
]

What I need to do is to access the values of the name and age keys and have them as a list like the following:

[['jamie', 'tara', 'matt'], [26, 43, 34]]

I know that if I need to create a list of a single key, I can print their values using the following code:

[d["name"] for d in l]

However, that code only returns the following output:

['jamie', 'tara', 'matt']

Could anyone help me how to return all values as list of lists? Also, considering that there are going to be many keys in my real list, it is possible to write the code in a way that I don't need to specify the key names?

CodePudding user response:

By using list comprehension twice, you can get what you want:

[[i['name'] for i in l], [i['age'] for i in l]]

Update

My assumptions:

  • Each dictionary has the same keys/values
  • You don't want to use pandas

My approach is

  1. Get the keys from one of the dictionaries, the first one will do
>>> keys = l[0].keys()   # key = ['name', 'age'] conceptually
  1. Transform the list of dicts into a list of tuples, where each tuple contains the values, in the correct order:
>>> [[i[k] for k in keys] for i in l]
[['jamie', 26], ['tara', 43], ['matt', 34]]
  1. Given this list of tuples, I can use a combination of list and zip to transpose them:
>>> list(zip([[i[k] for k in keys] for i in l]))
[('jamie', 'tara', 'matt'), (26, 43, 34)]

This should work for all dicts, provide that they have the same keys.

CodePudding user response:

You can use zip:

l = [{'name': 'jamie', 'age': 26, 'hobby': 'fishing'},
     {'name': 'tara', 'age': 43, 'hobby': 'soccer'},
     {'name': 'matt', 'age': 34, 'hobby': 'knitting'}]

output = list(zip(*(dct.values() for dct in l))) # first method
print(output)
# [('jamie', 'tara', 'matt'), (26, 43, 34), ('fishing', 'soccer', 'knitting')]

keys = l[0].keys() # second method
output = list(zip(*([dct[k] for k in keys] for dct in l)))
print(output)

Here, the first method works if the keys are ordered the same (so works on python 3.7 ). The second one works even if, say, the second dict is {'age': 43, 'name': 'tara', 'hobby': 'soccer'}.

CodePudding user response:

The above Implementation of l won't work, but if you used 'age' instead of age like this

l = [{'name': 'jamie', 'age': 26},
     {'name': 'tara', 'age': 43},
     {'name': 'matt', 'age': 34}
]

you could create two lists and loop through each dictionary like this.

names = []
ages = []
for d in l:
    names.append(d['name'])
    ages.append(d['age'])
names_ages  = [names,ages] 

names_ages would now be [['jamie', 'tara', 'matt'], [26, 43, 34]]

CodePudding user response:

First, I had to fix your dict input as the age key wasn’t a string. Below iterates the list of dicts once.


l = [{'name': 'jamie', 'age': 26},
     {'name': 'tara', 'age': 43},
     {'name': 'matt', 'age': 34}
]

names = []
ages = []

for row in l:
    names.append(row["name"])
    ages.append(row["age"])
    
output = [names, ages]
print(output)

# Output: [['jamie', 'tara', 'matt'], [26, 43, 34]]

I think without the list comprehension it is more readable.

Saw your requirement to not know the keys…

l = [{'name': 'jamie', 'age': 26},
     {'name': 'tara', 'age': 43},
     {'name': 'matt', 'age': 34}
]

from collections import defaultdict

value_lists = defaultdict(list)

for row in l:
    for k, v in row.items():
        value_lists[k].append(v)
        
# print(value_lists)

# if it must be list of lists
output = list(value_lists.values())

print(output)

# Output: [['jamie', 'tara', 'matt'], [26, 43, 34]]

CodePudding user response:

Here is how you can do it:

d1 = {} # Create an empty dictionary
for d in l:
    for k,val in d.items():
        if k in d1: # If the key is already in d1 then add the value
            d1[k].append(val) 
        else:
            d1[k] = [val] # Else create a list and add the first value

l1 = [val for k,val in d1.items()] # get all the list from d1
print(d1)
print(l1)

Output:

{'name': ['jamie', 'tara', 'matt'], 'age': [26, 43, 34]} # d1
[['jamie', 'tara', 'matt'], [26, 43, 34]] # l1

CodePudding user response:

This will go through all your dictionaries and compile the values for each key. It is not dependent on the dictionaries being the same, nor is it dependent on ordering.

from pprint import pprint

l = [{'name': 'jamie', 'age': 26, 'color': 'gold'},
     {'name': 'tara', 'age': 43, 'hobby': 'archery'},
     {'name': 'matt', 'age': 34, 'epic': 'louhi'}
]

def compile(ls):
    dx = dict()
    for d in ls:
        for k, v in d.items():
            current = dx.get(k, [])  # Leverage get() default value option 
            current.append(v)
            dx[k] = current
    return dx

result = compile(l)
pprint(result)

This yields the output:

{'age': [26, 43, 34],
 'color': ['gold'],
 'epic': ['louhi'],
 'hobby': ['archery'],
 'name': ['jamie', 'tara', 'matt']}

Dropping keys is simple if desired:

only_values = [v for _, v in result.items()]
  • Related