2

I want to create a program which accepts two dictionaries and then outputs two new ones, where the first one is going to contain elements that weren't in d1 but were in d2 and the other one is going to contain d1 and then appended elements from d2 that are not in d1.

Input:

dc1 = {'a': 3, 'b': 4, 'c': 5, 'd': 6, 'e': 7, 'f': 8, 'g': 9} 
dc2 = {'e': 20, 'f': 21, 'g': 22, 'h': 23, 'i': 24, 'j': 25, 'k': 26, 'l': 27}

Output:

dc3 = {'h': 23, 'i': 24, 'j': 25, 'k': 26, 'l': 27}
dc4 = {'a': 3, 'b': 4, 'c': 5, 'd': 6, 'e': 7, 'f': 8, 'g': 9, 'h': 23, 'i': 24, 'j': 25, 'k': 26, 'l': 27}

This is the code I've tried running however I can't understand how to properly compare dictionaries using a comprehension and create dc3 and dc4 in just one line. So I'm already facing a syntax error on creating dc3, so I haven't even started working on dc4:

d3 = {v: k for k,v in dic2 for z,x in dic1 if v: k in x:z}
d3

Output:

d3 = {v: k for k,v in dic2 for z,x in dic1 if v: k in x:z}
                                                   ^
SyntaxError: invalid syntax

If anyone can help me out how to properly use a comprehension here, I would really appreciate it.

wjandrea
  • 28,235
  • 9
  • 60
  • 81
chunk
  • 37
  • 5
  • `dc1.items() - dc2.items()` and `dc2.items() - dc1.items()` works as long as there are only immutable items in each dict. – dawg Oct 27 '20 at 16:49
  • I fixed the terminology in the question to make it clearer for the future: [generator (expression)](https://docs.python.org/3/glossary.html#term-generator-expression) -> [(dict) comprehension](https://docs.python.org/3/glossary.html#term-dictionary-comprehension) – wjandrea Oct 27 '20 at 20:11
  • For union: [How do I merge two dictionaries in a single expression in Python (taking union of dictionaries)?](https://stackoverflow.com/q/38987/7851470) – Georgy Oct 28 '20 at 13:16

4 Answers4

2

As you noticed, your syntax is a bit off. I would first assume that where you used in dic2 and in dic1 you meant to use in dic.items() to iterate over key:value pairs. Second, the : can basically only be in the first part of the dict-comp. I guess you meant:

dc3 = {k: v for k,v in dc2.items() if k not in dc1}
dc4 = {**dc1, **dc3}

The creation of dc3 just loops over the key:value pairs in dc2 and only adds them if they are not in dc1.

The creation of dc4 is just a dictionary merge of dc1 and the newly created dc3.

wjandrea
  • 28,235
  • 9
  • 60
  • 81
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
1

First, you're using comprehensions, not generators.

Second, the simple "in" will handle your comparisons: you don't need nested comprehension syntax.

Try something like this:

{key: val for key, val in dc1.items() if key not in dc2}
Prune
  • 76,765
  • 14
  • 60
  • 81
1

Set operations work on dictionary views.

So given:

>>> dc1
{'a': 3, 'b': 4, 'c': 5, 'd': 6, 'e': 7, 'f': 8, 'g': 9}
>>> dc2
{'e': 20, 'f': 21, 'g': 22, 'h': 23, 'i': 24, 'j': 25, 'k': 26, 'l': 27}

You can get what keys are common to both:

>>> dc1.keys() & dc2.keys()
{'e', 'f', 'g'}

And what keys are unique to each:

>>> dc1.keys() - dc2.keys()
{'b', 'a', 'd', 'c'}
>>> dc2.keys() - dc1.keys()
{'i', 'h', 'l', 'k', 'j'}

The same will work for keys and value (so long as the values are immutable; keys are by definition immutable):

>>> dc1.items() - dc2.items()
{('d', 6), ('e', 7), ('a', 3), ('f', 8), ('g', 9), ('c', 5), ('b', 4)}

So your output is:

>>> {k:v for k,v in dc2.items() if k in dc2.keys()-dc1.keys()}
{'h': 23, 'i': 24, 'j': 25, 'k': 26, 'l': 27}

and with Python 3.9:

>>> dc1 | dc2
{'a': 3, 'b': 4, 'c': 5, 'd': 6, 'e': 20, 'f': 21, 'g': 22, 'h': 23, 'i': 24, 'j': 25, 'k': 26, 'l': 27}

Or with earlier:

>>> {**dc1, **dc2}
{'a': 3, 'b': 4, 'c': 5, 'd': 6, 'e': 20, 'f': 21, 'g': 22, 'h': 23, 'i': 24, 'j': 25, 'k': 26, 'l': 27}
dawg
  • 98,345
  • 23
  • 131
  • 206
-1

I guess what you want is :

d3 = {v: k for k,v in dic6 for z,x in dic5 if k in z}

The : syntax is used for creating dict entries

TescoOne
  • 315
  • 1
  • 6
  • 1
    `k, v in dic6` won't work because iterating over a dict gets keys, not key-value pairs. Use `.items()` instead. As well, `if k in z` only works in this case since the keys are strings, but either way, you don't need to iterate over `dic5` when you could just check membership. `d3 = {v: k for k, v in dic6.items() if k in dic5}` – wjandrea Oct 27 '20 at 21:07