Skip to content

Instantly share code, notes, and snippets.

@karolzlot
Last active July 14, 2022 12:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save karolzlot/ee4a9aa04bdda1f204b531169a89b97f to your computer and use it in GitHub Desktop.
Save karolzlot/ee4a9aa04bdda1f204b531169a89b97f to your computer and use it in GitHub Desktop.
Get differences between two lists of dictonaries (result as two differences lists) in Python - this is a draft for a question which finally landed here: https://stackoverflow.com/questions/68091970/get-differences-between-two-lists-of-dictionaries-result-as-two-differences-lis

I have two lists of dictonaries. They contain gmail labels and filters. I need to get differences between them in form of two differences lists. I want order of the elements to be preserved.

Example:

a=[
	{'name': 'label_a'},
	{'color': {'background': '#42d692', 'text': '#094228'}, 'name': 'label_b'},
	{'name': 'label_d'},
	{'name': 'label_e'},
]

b=[
	{'name': 'label_a'},
	{'name': 'label_b'},
	{'name': 'label_c'},
	{'name': 'label_d'},
]

Expected results:

a_diff=[
	{'color': {'background': '#42d692', 'text': '#094228'}, 'name': 'label_b'},
	{'name': 'label_e'},
]

b_diff=[
	{'name': 'label_b'},
	{'name': 'label_c'},
]

This is how I could do this, but I think it might be inefficient. Can I do something better?

a_diff=[]
b_diff=[]

for i in a:
    if i not in b:
        a_diff.append(i)

for j in b:
    if j not in a:
        b_diff.append(j)

I don't need to keep original lists after this operation, so this can be in-place. Speed is most important. So this question can be also rephrased as: "How to remove common elements between two lists from those lists?"

When you provide solution, let know if it would work also on any two lists or only lists of dictonaries.

Also please let know if your solution will remove duplicates or not (I am interested in both kinds of solutions):

a=[
	{'name': 'label_a'},
	{'name': 'label_a'},
	{'name': 'label_b'},
]

b=[
	{'name': 'label_a'},
	{'name': 'label_b'},
	{'name': 'label_c'},
]

Results with removed duplicate.

a_diff=[
]

b_diff=[
	{'name': 'label_c'},
]

Results without removed duplicate.

a_diff=[
	{'name': 'label_a'},
]

b_diff=[
	{'name': 'label_c'},
]
@MoritzPlenz
Copy link

Hi, just in case you are still interested in a possible solution:

For the case with removed duplicates you can make use of sets:

def get_diff(a, b):
    # convert dicts to strings and lists to sets
    # converting dicts to strings is required since dicts are not hashable, so a list of dicts can not be converted to a set of dicts
    a = {json.dumps(item, sort_keys=True) for item in a}
    b = {json.dumps(item, sort_keys=True) for item in b}

    # get differences    
    a_diff = a - b
    b_diff = b - a

    # convert strings back to dicts and set back to list
    a_diff = [json.loads(item) for item in a_diff]
    b_diff = [json.loads(item) for item in b_diff]
    return a_diff, b_diff 

I did not test the run-time, but I would expect this method to be faster for long lists and small dicts.
I hope this helps!

@karolzlot
Copy link
Author

karolzlot commented Jul 14, 2022

@MoritzPlenz

Thanks.

This question was posted (after modifications) on SO: https://stackoverflow.com/questions/68091970/get-differences-between-two-lists-of-dictionaries-result-as-two-differences-lis
I updated description of this gist to make it clear.

If you want, you can post your solution as another answer.

@MoritzPlenz
Copy link

In that case sorry for the spam.
The answers on SO look good, so I won't copy my answer there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment