Basically I have created a function which takes two lists of dicts, for example:
oldList = [{'a':2}, {'v':2}]
newList = [{'a':4},{'c':4},{'e':5}]
My aim is to check for each dictionary key in the oldList and if it has the same dictionary key as in the newList update the dictionary, else append to the oldList.
So in this case the key 'a' from oldList will get updated with the value 4, also since the keys b and e from the newList don't exist in the oldList append the dictionary to the oldList. Therefore you get [{'a': 4}, {'v': 2}, {'b': 4}, {'e': 5}]
.
Is there a better way to do this?
def sortList(oldList, newList):
for new in newList: #{'a':4},{'c':4},{'e':5}
isAdd = True
for old in oldList: #{'a':2}, {'v':2}
if new.keys()[0] == old.keys()[0]: #a == a
isAdd = False
old.update(new) # update dict
if isAdd:
oldList.append(new) #if value not in oldList append to it
return oldList
sortedDict = sortList([{'a':2}, {'v':2}],[{'a':4},{'b':4},{'e':5}])
print sortedDict
[{'a': 4}, {'v': 2}, {'b': 4}, {'e': 5}]
-
4\$\begingroup\$ Why in the world do you have a list of single element dictionaries? \$\endgroup\$Winston Ewert– Winston Ewert2013年03月29日 22:34:04 +00:00Commented Mar 29, 2013 at 22:34
-
\$\begingroup\$ Please make an effort to name and structure questions appropriately. Because your code has nothing to do with sorting, I tried to find a better title—feel free to improve it further. \$\endgroup\$Adam– Adam2013年03月29日 23:33:20 +00:00Commented Mar 29, 2013 at 23:33
3 Answers 3
A list of 1-pair dictionaries makes no sense as data structure. You should join them to create a single dictionary. This way all your code reduces to:
d1 = {'a': 2, 'b': 2}
d2 = {'a': 4, 'c': 4, 'e': 5}
d3 = dict(d1, **d2)
# {'a': 4, 'b': 2, 'c': 4, 'e': 5}
If you are going to union/merge dicts a lot, you can create a handy abstraction, more general than dict(d1, **d2)
:
def merge_dicts(d1, d2):
return dict(itertools.chain(d1.items(), d2.items()))
To convert list of dictionaries to a dictionary is simple:
d2 = dict(list(d.items())[0] for d in new_list)
# {'a': 4, 'c': 4, 'e': 5}
-
\$\begingroup\$
d3 = dict(d1, **d2)
I didn't know about this behaviour; super useful. Thanks! \$\endgroup\$tegan– tegan2018年05月10日 18:31:01 +00:00Commented May 10, 2018 at 18:31
def sortList(oldList, newList):
Python convention is to lowercase_with_underscores for pretty much everything besides class names
for new in newList: #{'a':4},{'c':4},{'e':5}
isAdd = True
Avoid boolean flags. They are delayed gotos and make it harder to follow your code. In this case, I'd suggest using an else: block on the for loop.
for old in oldList: #{'a':2}, {'v':2}
if new.keys()[0] == old.keys()[0]: #a == a
isAdd = False
old.update(new) # update dict
if isAdd:
oldList.append(new) #if value not in oldList append to it
return oldList
sortedDict = sortList([{'a':2}, {'v':2}],[{'a':4},{'b':4},{'e':5}])
print sortedDict
Why are you calling it sortList? You are merging lists, not sorting anything...
Your whole piece of code would be quicker if implemented using dicts:
# convert the lists into dictionaries
old_list = dict(item.items()[0] for item in oldList)
new_list = dict(item.items()[0] for item in newList)
# actually do the work (python already has a function that does it)
old_list.update(new_list)
# covert back to the list format
return [{key:value} for key, value in old_list.items()]
All of which raises the question: why aren't these dicts already? What are you trying to do with this list of dicts stuff?
-
\$\begingroup\$ 1) Your right about the lowercase_with_underscores and the name of the function. 2) Your code snippet doesn't take order into account and will return
[{'a': 4}, {'b': 4}, {'e': 5}, {'v': 2}]
instead of[{'a': 4}, {'v': 2}, {'b': 4}, {'e': 5}]
. I guess ordereddict should be used instead \$\endgroup\$user1741339– user17413392013年03月29日 23:24:31 +00:00Commented Mar 29, 2013 at 23:24 -
\$\begingroup\$ @user1741339, or you could sort the result, if what you really want is for the keys to be in sorted order. Regardless, its still bizarre to have a list of single-element dicts like this. \$\endgroup\$Winston Ewert– Winston Ewert2013年03月29日 23:28:14 +00:00Commented Mar 29, 2013 at 23:28
You don't need the isAdd
flag, instead you can structure your for loops like this:
for new, old in newList, oldList:
if new.keys()[0] == old.keys()[0]:
old.update(new)
else:
oldList.append(new)
return oldList
As well, you might want to look at PEP documents for coding style
For reference, here is the rest of your code with those standards in place:
def sort_list(old_list, new_list):
for new, old in new_list, old_list:
if new.keys()[0] == old.keys()[0]:
old.update(new)
else:
old_list.append(new)
return old_list
sorted_dict = sort_list([{'a':2}, {'v':2}],[{'a':4},{'b':4},{'e':5}])
print sorted_dict
[{'a': 4}, {'v': 2}, {'b': 4}, {'e': 5}]
Oh, and I'm assuming you are doing this for practice/homework, but the dict.update(iterable) method does this exact thing far, far faster than you ever could.
-
1\$\begingroup\$ Yeah, I'm pretty sure that code doesn't do the same thing. His code only adds to the list if none of the keys match, yours will it for every non-matching key. Furthermore,
for new, old in new_list, old_list
? I'm pretty sure that's not what you meant. \$\endgroup\$Winston Ewert– Winston Ewert2013年03月29日 22:56:46 +00:00Commented Mar 29, 2013 at 22:56 -
\$\begingroup\$ Using his check (and multiple others) I got the code to produce the same output. \$\endgroup\$Preston Carpenter– Preston Carpenter2013年03月29日 22:59:59 +00:00Commented Mar 29, 2013 at 22:59
-
1\$\begingroup\$ Really? I get
ValueError: too many values to unpack
if I copy and paste your code from above. (After correcting a spacing error) \$\endgroup\$Winston Ewert– Winston Ewert2013年03月29日 23:03:30 +00:00Commented Mar 29, 2013 at 23:03