Convert nested lists to multiple dictionaries - python

lst = [['111', 'kam'],['222', 'Van']]
Header = ['ID', 'Name']
I want to convert the above list to dictionary based on the Headers. I can do this simply using for loop by taking each element in loop and append to some new list one by one.
But, I want to achieve the same without using loop to prevent from performance issue.
Is there any way to do that?
Expected Output:
[{'ID' : '111', 'Name' : 'Kam'},{'ID' : '222', 'Name' : 'Van'}]

You can use a list comprehension:
lst = [['111', 'kam'],['222', 'Van']]
Header = ['ID', 'Name']
result = [dict(zip(Header, row)) for row in lst]
print(result)
Output:
[{'ID': '111', 'Name': 'kam'}, {'ID': '222', 'Name': 'Van'}]

Related

Removing duplicates from a list of dictionaries in Python using deepcopy

I have a list of dictonaries:
list_1 = [{'account': '1234', 'email' : 'abc#xyz.com'}, ... , ...]
I wanted to remove the entries with duplicate emails in the list.
import copy
list_2 = copy.deepcopy(list_1)
for i in mainList
for j in range(len(list_2)-1, -1, -1):
if ((list_2[j]["email"] == mainList[i])):
list_1.remove(list1[j])
mainList here is the list of emails with which I am comparing values.
mainList looks like this:
['abc#xyz.com', 'efg#cvb.com, ..., ...]
The main problem is list_1 is not coming out correctly. If I use list, slicing or even list comprehension to copy it, it will come out empty.
The final result should give list_1 containing only one element/list/dictionary for each email.
Using copy or deepcopy at least gives me something. It also seems like sometimes I am getting an indexing error.
Using for x in list_2: instead returns list_1 with only one item.
The closest I got to the correct answer was iterating over list_1 itself while removing items, but it was not 100% correct.
iterate over your list of dictionaries and keep saving every email in a new dictionary only if it is not already present.
temp = dict()
list_1 = [{'account': '1234', 'email': 'abc#xyz.com'}]
for d in list_1:
if d['email'] in temp:
continue
else:
temp[d['email']] = d
final_list = list(temp.values())
Seems like you want to remove duplicate dictionaries. Please mention the duplicate dictionaries also in the problem.
di = [{'account': '1234', 'email' : 'abc#xyz.com'}, {'account1': '12345',
'email1' : 'abcd#xyz.com'}, {'account': '1234', 'email' : 'abc#xyz.com'}]
s=[i for n, i in enumerate(d) if i not in di[n + 1:]]
Print(s)
This would give you required output
[{'account1': '12345', 'email1': 'abcd#xyz.com'}, {'account': '1234', 'email':
'abc#xyz.com'}]
The easiest way I feel to accomplish this is to create an indexed version of list_1 (a dictionary) based on your key.
list_1 = [
{'account': '1234', 'email' : 'abc#xyz.com'},
{'account': '1234', 'email' : 'abc#xyz.com'},
{'account': '4321', 'email' : 'zzz#xyz.com'},
]
list_1_indexed = {}
for row in list_1:
list_1_indexed.setdefault(row['email'], row)
list_2 = list(list_1_indexed.values())
print(list_2)
This will give you:
[
{'account': '1234', 'email': 'abc#xyz.com'},
{'account': '4321', 'email': 'zzz#xyz.com'}
]
I'm not sure I would recommend it, but if you wanted to use a comprehension you might do:
list_2 = list({row['email']: row for row in list_1}.values())
Note that the first strategy results in the first key row wins and the comprehension the last key row wins.

Adding multiple dictionaries of list based on semi column in python

I have the data
data = [{'name': 'Dave', 'role': 'Manager'}, {'name': 'David', 'role': 'Engineer'}]
I am intending to add the values based on same keys and merging it by semicolon.
Expected output is like this as follows
{'name': 'Dave;David', 'role': 'Manager;Engineer'}
What I am trying to do is to convert into matrix then adding all the elements based on the index but it is very tedious approach.
result = [[i[e] for e in sorted(i.keys())] for i in data]
print(result)
current output: [['Dave', 'Manager'], ['David', 'Engineer']]
The following does what you want, assuming that data always contains dictionaries of strings.
I'm checking if each dictionary key already exists in the final dictionary. If it doesn't I add it, if it does I append it to the current value using the semicolon as a separator.
data = [{'name': 'Dave', 'role': 'Manager'}, {'name': 'David', 'role': 'Engineer'}]
final = {}
for dict in data:
for k,v in dict.items():
if k in final:
final[k] += ';' + v
else:
final[k] = v
print(final)

Python - Return list of dictionaries with unique Key:Value pair

I have a long list of dictionaries that for the most part do not overlap. However, some of the dictionaries have the same 'Name' field and I'd only like unique names in the list of dictionaries. I'd like the first occurrence of the name to be the one that stays and any thereafter be deleted from the list.
I've put a short list below to illustrate the scenario:
myList = [
{'Name':'John', 'Age':'50', 'Height':'70'},
{'Name':'Kathy', 'Age':'43', 'Height':'65'},
{'Name':'John','Age':'46','Height':'68'},
{'Name':'John','Age':'50','Height':'72'}
]
I'd like this list to return the first 'John' and Kathy, but not the second or third Johns and their related information.
An acceptable, but not optimal solution would also be not having dictionaries with the same name next to each other.
You could run over the list and keep a set of unique names. Every time you encounter a new name (i.e., a name that isn't in the set), you add it to the set and the respective dict to the result:
def uniqueNames(dicts):
names = set()
result = []
for d in dicts:
if not d['Name'] in names:
names.add(d['Name'])
result.append(d)
return result
You can easily write a for-loop for this.
def getName(name):
'''Gets first occurence of name in list of dicts.'''
for i in myList:
if i['Name'] == name:
return i
Initial list:
my_list = [
{'Name':'John', 'Age':'50', 'Height':'70'},
{'Name':'Kathy', 'Age':'43', 'Height':'65'},
{'Name':'John','Age':'46','Height':'68'},
{'Name':'John','Age':'50','Height':'72'}
]
The logical (potentially newbie-friendlier) way:
names = set()
new_list = []
for d in my_list:
name = d['Name']
if name not in names:
new_list.append(d)
names.add(d['Name'])
print new_list # [{'Age': '50', 'Name': 'John', 'Height': '70'}, {'Age': '43', 'Name': 'Kathy', 'Height': '65'}]
A one-liner way:
new_list = {d['Name']: d for d in reversed(my_list)}.values()
print new_list # [{'Age': '43', 'Name': 'Kathy', 'Height': '65'}, {'Age': '50', 'Name': 'John', 'Height': '70'}]
Note: The one-liner will contain the first occurrence of each name, but it will return an arbitrarily ordered list.

Reconstruct the list of dict in python but the result is not in order

list_1 = [{'1': 'name_1', '2': 'name_2', '3': 'name_3',},
{'1': 'age_1', '2': 'age_2' ,'3': 'age_3',}]
I want to manipulate this list so that the dicts contain all the attributes for a particular ID. The ID itself must form part of the resulting dict. An example output is shown below:
list_2 = [{'id' : '1', 'name' : 'name_1', 'age': 'age_1'},
{'id' : '2', 'name' : 'name_2', 'age': 'age_2'},
{'id' : '3', 'name' : 'name_3', 'age': 'age_3'}]
Then I did following:
>>> list_2=[{'id':x,'name':list_1[0][x],'age':list_1[1][x]} for x in list_1[0].keys()]
Then it gives:
>>> list_2
[{'age': 'age_1', 'id': '1', 'name': 'name_1'},
{'age': 'age_3', 'id': '3', 'name': 'name_3'},
{'age': 'age_2', 'id': '2', 'name': 'name_2'}]
But I don't understand why 'id' is showing in the second position while 'age' showing first?
I tried other ways but the result is the same. Any one can help to figure it out?
To keep the order, you should use an ordered dictionary. Using your sample:
new_list = [OrderedDict([('id', x), ('name', list_1[0][x]), ('age', list_1[1][x])]) for x in list_1[0].keys()]
Printing the ordered list...
for d in new_list:
print(d[name], d[age])
name_1 age_1
name_3 age_3
name_2 age_2
Try using an OrderedDict:
list_1 = [collections.OrderedDict([('1','name_1'), ('2', 'name_2'), ('3', 'name_3')]),
collections.OrderedDict([('1','age_1'),('2','age_2'),('3', 'age_3')])]
list_2=[collections.OrderedDict([('id',x), ('name',list_1[0][x]), ('age', list_1[1][x])])
for x in list_1[0].keys()]
This is more likely to preserve the order you want. I am still new to Python, so this may not be super Pythonic, but I think it will work.
output -
In [24]: list( list_2[0].keys() )
Out[24]: ['id', 'name', 'age']
Docs:
https://docs.python.org/3/library/collections.html#collections.OrderedDict
Examples:
https://pymotw.com/2/collections/ordereddict.html
Getting the constructors right:
Right way to initialize an OrderedDict using its constructor such that it retains order of initial data?

string to list of dictionaries (python)

I have a string that needs to be split 3 ways and then into a list of dictionaries.
given_string = 'name:mickey,age:58|name:minnie,age:47,weight:60'
data = []
data = [value.split(',') for value in given_string.split('|')]
data = [['name:mickey', 'age:58'], ['name:minnie', 'age:47', 'weight:60']]
Now I want to split this one more time on the ':' and have the data contain a list of two dictionaries so that when I input say data[1][age], I get 47.
Basically, I think I want this for it to work:
data = [{'name': 'mickey', 'age': '58}, {'name': 'minnie', 'age': '47', 'weight': '60'}]
I believe that ultimately, data should be a list of dictionaries but once I split the string into two lists, I get confused in splitting it on the ':' and then converting the sublists to a dictionary.
You can do with a simple list comprehension
>>> [dict(x.split(':') for x in parts.split(','))
for parts in given_string.split('|')]
[{'age': '58', 'name': 'mickey'}, {'age': '47', 'name': 'minnie', 'weight': '60'}]
Nest harder.
>>> [ dict(y.split(':') for y in x.split(',')) for x in 'name:mickey,age:58|name:minnie,age:47,weight:60'.split('|')]
[{'age': '58', 'name': 'mickey'}, {'age': '47', 'name': 'minnie', 'weight': '60'}]
given_string = 'name:mickey,age:58|name:minnie,age:47,weight:60'
data = [value.split(',') for value in given_string.split('|')]
y=[] # make a empty list
for i in data:
z={}
for v in range(len(i)):
b=i[v].split(":") # ['name", "mickey', 'age","58"]
z[b[0]]=b[1] # adding keys and values in dictionary z
y.append(z) # adding dictionary to the list

Categories