Sort the keys of a dictionary in python - python

dict:
d1 = {'b,a':12,'b,c,a':13}
Code:
x = collections.OrderedDict(sorted(d1.items()))
print(x)
Not getting the expected output.
Expected Output:
d1 = {'a,b': 12, 'a,b,c':13}

It looks like you don't actually want to sort the keys, you want to re-arrange the non-comma substrings of your keys such that these substrings are ordered.
>>> d1 = {'b,a':12,'b,c,a':13}
>>> {','.join(sorted(key.split(','))):val for key, val in d1.items()}
{'a,b': 12, 'a,b,c': 13}

d1.items(): returns a list of (key, value) tuples
sorted(d1.items()): simply sorts the above list
If you want to sort the items in your keys, then you need to run sort on your keys.

Related

Transform dictionary key-value pairs to list of tuples

I have a dictionary of lists:
dic = {'contig_100003': ['contig_14576'], 'contig_100022': ['contig_96468'], 'contig_100023': ['contig_24939', 'contig_33444', 'contig_72441']}
And I would like to get a list (including the key) of it:
List = [(contig_100003','contig_14576'), (contig_100022','contig_96468'), (contig_100023','contig_24939', 'contig_33444', 'contig_72441')]
However, my code cannot get rid of the internal/value list:
list(dic.items())
[('contig_100003', ['contig_14576']),
('contig_100022', ['contig_96468']),
('contig_100023', ['contig_24939', 'contig_33444', 'contig_72441'])]
This might solve it
[(k, *v) for k, v in dic.items()]
You can use tuple concatenation to get the desired output:
result = [(key,) + tuple(value) for key, value in dic.items()]
print(result)
This outputs:
[('contig_100003', 'contig_14576'), ('contig_100022', 'contig_96468'),
('contig_100023', 'contig_24939', 'contig_33444', 'contig_72441')]

Split dictionaries into different dictionaries based on the key in python?

Suppose I have a dictionary:
d = {'a_c':1,'b_c':2,'a_d':3,'b_d':4}
how do I split into two based on the last word/letter of the key ('c','d') like this?
d1 = {'a_c':1,'b_c':2}
d2 = {'a_d':3,'b_d':4}
This is one way:
from collections import defaultdict
d = {'a_c':1,'b_c':2,'a_d':3,'b_d':4}
key = lambda s: s.split('_')[1]
res = defaultdict(dict)
for k, v in d.items():
res[key(k)][k] = v
print(list(res.values()))
Output:
[{'a_c': 1, 'b_c': 2}, {'a_d': 3, 'b_d': 4}]
The result is a list of dictionaries divided on the last letter of the key.
You could try something like this:
func = lambda ending_str: {x: d[x] for x in d.keys() if x.endswith(ending_str)}
d1 = func('_c')
d2 = func('_d')
Also, like Marc mentioned in the comments, you shouldn't have two same name keys in the dictionary. It will only keep the last key/value pair in that case.

Sort list of dictionaries based on keys

I want to sort a list of dictionaries based on the presence of keys. Let's say I have a list of keys [key2,key3,key1], I need to order the list in such a way the dictionary with key2 should come first, key3 should come second and with key1 last.
I saw this answer (Sort python list of dictionaries by key if key exists) but it refers to only one key
The sorting is not based on value of the 'key'. It depends on the presence of the key and that too with a predefined list of keys.
Just use sorted using a list like [key1 in dict, key2 in dict, ...] as the key to sort by. Remember to reverse the result, since True (i.e. key is in dict) is sorted after False.
>>> dicts = [{1:2, 3:4}, {3:4}, {5:6, 7:8}]
>>> keys = [5, 3, 1]
>>> sorted(dicts, key=lambda d: [k in d for k in keys], reverse=True)
[{5: 6, 7: 8}, {1: 2, 3: 4}, {3: 4}]
This is using all the keys to break ties, i.e. in above example, there are two dicts that have the key 3, but one also has the key 1, so this one is sorted second.
I'd do this with:
sorted_list = sorted(dict_list, key = lambda d: next((i for (i, k) in enumerate(key_list) if k in d), len(key_list) + 1))
That uses a generator expression to find the index in the key list of the first key that's in each dictionary, then use that value as the sort key, with dicts that contain none of the keys getting len(key_list) + 1 as their sort key so they get sorted to the end.
How about something like this
def sort_key(dict_item, sort_list):
key_idx = [sort_list.index(key) for key in dict_item.iterkeys() if key in sort_list]
if not key_idx:
return len(sort_list)
return min(key_idx)
dict_list.sort(key=lambda x: sort_key(x, sort_list))
If the a given dictionary in the list contains more than one of the keys in the sorting list, it will use the one with the lowest index. If none of the keys are present in the sorting list, the dictionary is sent to the end of the list.
Dictionaries that contain the same "best" key (i.e. lowest index) are considered equal in terms of order. If this is a problem, it wouldn't be too hard to have the sort_key function consider all the keys rather than just the best.
To do that, simply return the whole key_idx instead of min(key_idx) and instead of len(sort_list) return [len(sort_list)]

How to get all keys from dictionary that specified values?

If I have dict like this:
some_dict = {'a': 1, 'b': 2, 'c': 2}
How to get keys that have values 2, like this:
some_dict.search_keys(2)
This is example. Assume some_dict is has many thousands or more keys.
You can do it like this:
[key for key, value in some_dict.items() if value == 2]
This uses a list comprehension to iterate through the pairs of (key, value) items, selecting those keys whose value equals 2.
Note that this requires a linear search through the dictionary, so it is O(n). If this performance is not acceptable, you will probably need to create and maintain another data structure that indexes your dictionary by value.
you can also use dictionary comprehension, if you want result to be dictionary
{ x:y for x,y in some_dict.items() if y == 2}
output:
{'c': 2, 'b': 2}
Well, you can use generator to produce found key values, one by one, instead of returning all of them at once.
The function search_keys returns generator
def search_keys(in_dict, query_val):
return (key for key, val in in_dict.iteritems() if val == query_val)
# get keys, one by one
for found_key in search_keys(some_dict, 2):
print(found_key)

Reversing dictionary by key doesn't work

I have a following dictionary :
{2009: [12, 11, 10, 9], 2010: [1]}
I'm trying to reverse-sort it, so that 2010 comes first. Here's the code :
def dictSort(dict):
items = dict.items()
items.sort(reverse=True)
dict = {}
for item in items:
dict[item[0]] = item[1]
return dict
But in return I get the same dictionary. Until the for loop everything looks fine. Why is that ?
Dictionary keys are not ordered. Think of a dict as a set of key/value pairs.
This is coming in Python 3.1:
http://docs.python.org/dev/library/collections.html#collections.OrderedDict
A dictionary is unordered, whatever you put into it isn't stored in the order you add to it.
If you want to do something to it in sorted order, you can do:
items = dict.items.sort(reverse=True)
for item in items:
doSomething(item,mydict[item])
or
for key,value in iter(sorted(mydict.iteritems(),reverse=True))
doSomething(key,value)
Dictionaries don't have an order. If you are trying to output the dictionary in a certain order, try grabbing all the keys, sorting them, and using that list to know which order to output things.
Here one way to generate items of dict in reversed order of key (BTW please do not use dict for variable name!):
def dict_sort(thisdict, reverse=True):
return ((key, thisdict[key]) for key in sorted(thisdict, reverse=reverse))
mydict = {2009: [12, 11, 10, 9], 2010: [1]}
for i in dict_sort(mydict):
print "%i: %s" % i

Categories