1
\$\begingroup\$

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}]
\$\endgroup\$
2
  • 4
    \$\begingroup\$ Why in the world do you have a list of single element dictionaries? \$\endgroup\$ 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
    Mar 29, 2013 at 23:33

3 Answers 3

3
\$\begingroup\$

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}
\$\endgroup\$
1
  • \$\begingroup\$ d3 = dict(d1, **d2) I didn't know about this behaviour; super useful. Thanks! \$\endgroup\$
    – tegan
    May 10, 2018 at 18:31
1
\$\begingroup\$
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?

\$\endgroup\$
2
  • \$\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\$ 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\$ Mar 29, 2013 at 23:28
0
\$\begingroup\$

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.

\$\endgroup\$
3
  • 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\$ Mar 29, 2013 at 22:56
  • \$\begingroup\$ Using his check (and multiple others) I got the code to produce the same output. \$\endgroup\$ 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\$ Mar 29, 2013 at 23:03

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.