Reputation: 11476
I have two dictionaries,i want to combine these two int a list in the format keys-->values,keys-->values... remove any None or ['']
currently I have the below where I can combine the dicts but not create a combined lists...i have the expecte output.. any inputs appreeciated
dict1={'313115': ['313113'], '311957': None}
dict2={'253036': [''], '305403': [], '12345': ['']}
dict = dict(dict1.items() + dict2.items())
print dict
{'313115': ['313113'], '311957': None, '253036': [''], '12345': [''], '305403': []}
EXPECTED OUTPUT:
['313115','313113','311957','253036','305403','12345']
Upvotes: 3
Views: 240
Reputation: 7129
[each
if isinstance(each, str) else each[0]
for pair in dict(dict1, **dict2).iteritems()
for each in pair
if each not in [[''], None, []]]
Upvotes: 0
Reputation: 18985
This should do it:
[i for k, v in (dict1.items() + dict2.items()) for i in [k] + (v or []) if i]
walk the combined items of the two dicts, then walk the key plus the list of values, returning each item from the second walk that exists.
Returns ['313115', '313113', '311957', '253036', '12345', '305403']
on your example dicts -- the order is different because python's dict iteration is unordered.
EDIT:
dict.items()
can be expensive on large dicts -- it takes O(n) size, rather than iterating. If you use itertools, this is more efficient (and keeps the dicts you're working with in one place):
import itertools
[i
for k, v in itertools.chain.from_iterable(d.iteritems() for d in (dict1, dict2))
for i in [k] + (v or [])
if i]
Thanks to Martijn Pieters for the from_iterable tip.
Upvotes: 5
Reputation: 1123570
The following line gives you what you want in as efficient a manner as possible, albeit a little verbose:
from itertools import chain, ifilter
list(ifilter(None, dict1.viewkeys() | dict2.viewkeys() | set(chain(chain.from_iterable(ifilter(None, dict1.itervalues())), chain.from_iterable(ifilter(None, dict2.itervalues()))))))
You could break it down to:
values1 = chain.from_iterable(ifilter(None, dict1.itervalues()))
values2 = chain.from_iterable(ifilter(None, dict2.itervalues()))
output = list(ifilter(None, dict1.viewkeys() | dict2.viewkeys() | set(chain(values1, values2))))
ifilter
with a None
filter removes false-y values such as None
and ''
from the iterable. the outer filter is not needed for your specific input but would remove ''
and None
if used as keys as well. Duplicate values are removed.
Ordering in Python dictionaries is arbitrary so ordering doesn't match your sample but all expected values are there.
Demo:
>>> list(ifilter(None, dict1.viewkeys() | dict2.viewkeys() | set(chain(chain.from_iterable(ifilter(None, dict1.itervalues())), chain.from_iterable(ifilter(None, dict2.itervalues()))))))
['313115', '305403', '313113', '311957', '253036', '12345']
Upvotes: 1