Create a list of unique keys in Python - python

I have a list of
[{"1":"value"},{"1":"second_value"},{"2":"third_value"},{"2":"fourth_value"},{"3":"fifth_value"}]
want to convert it into
[{"1":"value","2":"third_value","3":"fifth_value"},{"1":"second_value","2":"fourth_value"}]

There is probably a cleaner way of doing this, input is appreciated:
d = [{"1":"value"},{"1":"second_value"},{"2":"third_value"},{"2":"fourth_value"},{"3":"fifth_value"}]
results = [{}]
for item in stuff:
j,k = item.items()[0] // Do the initial dicts always contain one key-value pair?
for result in results:
if j not in result:
result[j] = k
break
if result == results[-1]:
results.append(item)
break
Result:
[{'1': 'value', '3': 'fifth_value', '2': 'third_value'}, {'1': 'second_value', '2': 'fourth_value'}]

You can use collections.defaultdict:
>>> import collections
>>> result = collections.defaultdict(list)
>>> for item in d:
... result[item.values()[0]].append(item.keys()[0])
...
>>> [{key: value for key in keys} for value, keys in result.items()]
[{'1': 'second_value', '2': 'second_value'}, {'1': 'value', '3': 'value', '2': 'value'}]
Note that second_value comes before value in this as the ordering is rather arbitrary (unless you were to explicitly specify that value should be ordered before second_value the above would give you the ordering that the dictionary returns).

You can use collections.defaultdict here. Iterate over the list, use the values as keys and collect all the keys related to a value in a list.
>>> from collections import defaultdict
>>> d = defaultdict(list)
for dic in lis:
for k, v in dic.items():
d[v].append(k)
...
Now d becomes:
>>> d
defaultdict(<type 'list'>,
{'second_value': ['1', '2'],
'value': ['1', '2', '3']})
Now iterate over d to get the desired result:
>>> [{v1:k for v1 in v} for k, v in d.items()]
[{'1': 'second_value', '2': 'second_value'}, {'1': 'value', '3': 'value', '2': 'value'}]

Related

How to merge data from multiple dictionaries with repeating keys?

I have two dictionaries:
dict1 = {'a': '2', 'b': '10'}
dict2 = {'a': '25', 'b': '7'}
I need to save all the values for same key in a new dictionary.
The best i can do so far is: defaultdict(<class 'list'>, {'a': ['2', '25'], 'b': ['10', '7']})
dd = defaultdict(list)
for d in (dict1, dict2):
for key, value in d.items():
dd[key].append(value)
print(dd)
that does not fully resolve the problem since a desirable result is:
a = {'dict1':'2', 'dict2':'25'}
b = {'dict2':'10', 'dict2':'7'}
Also i possibly would like to use new dictionary key same as initial dictionary name
Your main problem is that you're trying to cross the implementation boundary between a string value and a variable name. This is almost always bad design. Instead, start with all of your labels as string data:
table = {
"dict1": {'a': '2', 'b': '10'},
"dict2": {'a': '25', 'b': '7'}
}
... or, in terms of your original post:
table = {
"dict1": dict1,
"dict2": dict2
}
From here, you should be able to invert the levels to obtain
invert = {
"a": {'dict1': '2', 'dict2': '25'},
"b": {'dict2': '10', 'dict2': '7'}
}
Is that enough to get your processing where it needs to be? Keeping the data in comprehensive dicts like this, will make it easier to iterate through the sub-dicts as needed.
As #Prune suggested, structuring your result as a nested dictionary will be easier:
{'a': {'dict1': '2', 'dict2': '25'}, 'b': {'dict1': '10', 'dict2': '7'}}
Which could be achieved with a dict comprehension:
{k: {"dict%d" % i: v2 for i, v2 in enumerate(v1, start=1)} for k, v1 in dd.items()}
If you prefer doing it without a comprehension, you could do this instead:
result = {}
for k, v1 in dd.items():
inner_dict = {}
for i, v2 in enumerate(v1, start=1):
inner_dict["dict%d" % i] = v2
result[k] = inner_dict
Note: This assumes you want to always want to keep the "dict1", "dict2",... key structure.

Convert list to dictionary with duplicate keys using dict comprehension [duplicate]

This question already has answers here:
How can one make a dictionary with duplicate keys in Python?
(9 answers)
Closed 6 months ago.
Good day all,
I am trying to convert a list of length-2 items to a dictionary using the below:
my_list = ["b4", "c3", "c5"]
my_dict = {key: value for (key, value) in my_list}
The issue is that when a key occurrence is more than one in the list, only the last key and its value are kept.
So in this case instead of
my_dict = {'c': '3', 'c': '5', 'b': '4'}
I get
my_dict = {'c': '5', 'b': '4'}
How can I keep all key:value pairs even if there are duplicate keys.
Thanks
For one key in a dictionary you can only store one value.
You can chose to have the value as a list.
{'b': ['4'], 'c': ['3', '5']}
following code will do that for you :
new_dict = {}
for (key, value) in my_list:
if key in new_dict:
new_dict[key].append(value)
else:
new_dict[key] = [value]
print(new_dict)
# output: {'b': ['4'], 'c': ['3', '5']}
Same thing can be done with setdefault. Thanks #Aadit M Shah for pointing it out
new_dict = {}
for (key, value) in my_list:
new_dict.setdefault(key, []).append(value)
print(new_dict)
# output: {'b': ['4'], 'c': ['3', '5']}
Same thing can be done with defaultdict. Thanks #MMF for pointing it out.
from collections import defaultdict
new_dict = defaultdict(list)
for (key, value) in my_list:
new_dict[key].append(value)
print(new_dict)
# output: defaultdict(<class 'list'>, {'b': ['4'], 'c': ['3', '5']})
you can also chose to store the value as a list of dictionaries:
[{'b': '4'}, {'c': '3'}, {'c': '5'}]
following code will do that for you
new_list = [{key: value} for (key, value) in my_list]
If you don't care about the O(n^2) asymptotic behaviour you can use a dict comprehension including a list comprehension:
>>> {key: [i[1] for i in my_list if i[0] == key] for (key, value) in my_list}
{'b': ['4'], 'c': ['3', '5']}
or the iteration_utilities.groupedby function (which might be even faster than using collections.defaultdict):
>>> from iteration_utilities import groupedby
>>> from operator import itemgetter
>>> groupedby(my_list, key=itemgetter(0), keep=itemgetter(1))
{'b': ['4'], 'c': ['3', '5']}
You can use defaultdict to avoid checking if a key is in the dictionnary or not :
from collections import defaultdict
my_dict = defaultdict(list)
for k, v in my_list:
my_dict[k].append(v)
Output :
defaultdict(list, {'b': ['4'], 'c': ['3', '5']})

how can I convert python tuple to dict

How can I convert the following list of tuples:
t = [("x", "1","11"),("x", "2","22"),("x", "3","33"),
("y", "3","00"),("z", "2","222"), ("z", "3","333")]
to this list of lists with dictionaries?
[["x",{"1":"11","2":"22","3":"33"}],
["y",{"3":"00"}],
["z",{"2":"222","3":"333"}]]
I'm a big fan of list comprehension. Here's a simple solution using it:
keys = set(map(lambda x: x[0], t))
d = [[k, dict([(y, z) for x, y, z in t if x is k])] for k in keys]
Result:
[['y', {'3': '00'}],
['x', {'1': '11', '2': '22', '3': '33'}],
['z', {'2': '222', '3': '333'}]]
This will be slow for larger lists as d is computed in O(N^2) time.
In two steps: create a dictionary and track the order you've seen the first elements, then build a list from that:
order = []
mapping = {}
for outer, inner, value in t:
if outer not in order:
order.append(outer)
mapping.setdefault(outer, {})[inner] = value
result = [(k, mapping[k]) for k in order]
or use a collections.OrderedDict() object to track the order you first saw the outer keys in:
from collections import OrderedDict
mapping = OrderedDict()
for outer, inner, value in t:
mapping.setdefault(outer, {})[inner] = value
result = mapping.items()
If order isn't important, use the first version and remove all references to order (3 lines), and just use mapping.items() at the end.
If your input is always sorted on the first element of each tuple, you can use itertools.groupby():
from itertools import groupby
from operator import itemgetter
result = [(k, {k: v for _, k, v in g}) for k, g in groupby(t, itemgetter(0))]
Demo:
>>> t = [("x", "1","11"),("x", "2","22"),("x", "3","33"),
... ("y", "3","00"),("z", "2","222"), ("z", "3","333")]
>>> order = []
>>> mapping = {}
>>> for outer, inner, value in t:
... if outer not in order:
... order.append(outer)
... mapping.setdefault(outer, {})[inner] = value
...
>>> [(k, mapping[k]) for k in order]
[('x', {'1': '11', '3': '33', '2': '22'}), ('y', {'3': '00'}), ('z', {'3': '333', '2': '222'})]
>>> mapping.items() # ignoring order
[('y', {'3': '00'}), ('x', {'1': '11', '3': '33', '2': '22'}), ('z', {'3': '333', '2': '222'})]
>>> from collections import OrderedDict
>>> mapping = OrderedDict()
>>> for outer, inner, value in t:
... mapping.setdefault(outer, {})[inner] = value
...
>>> mapping.items()
[('x', {'1': '11', '3': '33', '2': '22'}), ('y', {'3': '00'}), ('z', {'3': '333', '2': '222'})]
>>> from itertools import groupby
>>> from operator import itemgetter
>>> [(k, {k: v for _, k, v in g}) for k, g in groupby(t, itemgetter(0))]
[('x', {'1': '11', '3': '33', '2': '22'}), ('y', {'3': '00'}), ('z', {'3': '333', '2': '222'})]

specific value based filtering on a large dictionary in Python

I am having a very large dictionary. Here is a small sampling of my dictionary:
dictionary = {'1': {'a':'aa','b':'bb','c':'cc','d':'dd'},
'2': {'a':'aa','b':'bb','c':'cc','d':'dd'},
'3': {'a':'aa','b':'bb','c':'cc','d':'dd'} }
I just want to filter out the a & c.
Desired output:
dictionary = { '1': {'a':'aa','c':'cc'},
'2': {'a':'aa','c':'cc'},
'3': {'a':'aa','c':'cc'} }
Dictionary comprehensions to the rescue:
{k: {'a': v['a'], 'c': v['c']} for k, v in dictionary.iteritems()}
This assumes that all dictionaries in have those keys set and that you are using Python 2.7.
A more generic version:
def filtered_dicts(d, keys):
return {k: {vk: v[vk] for vk in v.viewkeys() & keys} for k, v in d.iteritems()}
dictionary = filtered_dicts(dictionary, {'a', 'c'})
This will work even if the keys are not present in all values of dictionary.
Any iterable will do for keys here; I used a set literal here but a list or tuple or even a string would work too.
A Python 3 version of the latter:
def filtered_dicts(d, keys):
return {k: {vk: v[vk] for vk in v.keys() & keys} for k, v in d.items()}
Quick demo using Python 3:
>>> dictionary = {'1': {'a':'aa','b':'bb','c':'cc','d':'dd'}, '2': {'a':'aa','b':'bb','c':'cc','d':'dd'}, '3':{'a':'aa','b':'bb','c':'cc','d':'dd'}}
>>> def filtered_dicts(d, keys):
... return {k: {vk: v[vk] for vk in v.keys() & keys} for k, v in d.items()}
...
>>> filtered_dicts(dictionary, {'a', 'c'})
{'3': {'c': 'cc', 'a': 'aa'}, '2': {'c': 'cc', 'a': 'aa'}, '1': {'c': 'cc', 'a': 'aa'}}

Python : What's wrong with the dictionary comprehension?

My Code :
dict( (k,v) if k in ['1','2','3','4'] else (k,None) for k,v in {'1':'one','2':'two'}.items() )
Expected Output :
{'1': 'one', '2': 'two', '3':None, '4':None}
Actual Output :
{'1': 'one', '2': 'two'}
Please help !
The for clause only contains 2 items, so your final dict is only going to have 2 items. The 4-item list is only used as a comparison, not as a source of values to use.
if k in ['1','2','3','4']
is a condition, not an iteration (see the if).
You can write it as:
dict((k, {'1':'one','2':'two'}.get(k, None)) for k in ['1','2','3','4'])
# returns: {'1': 'one', '2': 'two', '3': None, '4': None}
This would give the required result, as you need to traverse the list for 4 elements, and then assign respective values in the dictionary :
theDict = {'1':'one','2':'two'}
s = dict( (k,theDict[k]) if k in theDict else (k,None) for k in ['1','2','3','4'] )
u iterate over a dict with two keys, not a 4-element list
my code:
dict( (k, {'1':'one', '2':'two'}.get(k, None)) for k in ['1', '2','3', '4'])
If my crystal ball wasn't broken, I would guess you want the other direction: iterate k over the list and check if it is in the dictionary.
In this case, you might find useful
l = ['1', '2', '3', '4']
testdict = {'1': 'one', '2': 'two'}
res = dict((k, testdict.get(k, None)) for k in l)
This iterates over l and yields a (k, testdict[k]) tuple if k is in the testdict.
If not, it yields (k, None) - exactly as you (supposedly!) want.

Categories

Resources