Sort a dictionary based on alphanumeric keys - python-3.x

I have a dictionary that has alphanumeric keys and I need to sort them based on increasing order of numeric value of the key.Below is my dictionary
output_filters = {"filter22": "red", "filter13": "green", "filter36": "yellow"}
I want the final dictionary to be sorted like below
output_filters = {"filter13": "green", "filter22": "red", "filter36": "yellow"}
Now I know there are similar stackoverflow questions out there but I am not able to adapt it to my situation.
This is what I have done so far, but it doesn't work
def key_func(s):
return [int(x) if x.isdigit() else x for x in re.findall(r'\D+|\d+', s)]
sorted_keys = sorted(output_filters, key=key_func)
It gives inaccurate result.How can this be done?

The following will give you a sorted List of keys.
x = [k for k, v in output_filters.items()]
x = sorted(x, key=lambda x: int(x[6:])) # this will remove "filter" prefix
# ['filter13', 'filter22', 'filter36']
However, you can't sort a dictionary. They are unordered. If you really need it to be sorted, then you will need to use OrderedDict. It is an official built-in module that comes with python itself.
https://docs.python.org/2/library/collections.html#collections.OrderedDict

Related

Iterate through dictionary by indexes

How to bypass python out of box mechanism when an order of items() in the loop does not correspond to the order it supposes to be?
st = 'Tree'
freq = Counter(st)
sorted(freq.items(), key=lambda item: item[1])
arr = []
for k, v in freq.items():
for i in range(v):
arr.append(k)
I expect to get in the first iteration pair: ('e', 2), but instead it is ('t', 1).
But sorting was applied to dictionary at row 3.
How to iterate dictionary in way it is sorted? (without applying underhood re-order)
UPD. The question has already been answered, however, will be good to know why dictionaries implemented in Python3 in that way.
sort by keys:
a = dict(b=3, c=5, a=10)
for k in sorted(a):
print(f"{k}: {a[k]}")
and if you want to sort them by the values:
a = dict(b=3, c=5, a=10)
for k, v in sorted(a.items(), key=lambda item: item[1]):
print(f"{k}: {a[k]}")

Python3 - Combine Dictionaries with existing key value pairs

So... I know we can combine 2 dictionaries from python 3.5 like so:
z = {**x,**y} # x,y are 2 similar dictionaries, with nested entries
But in this method, any conflicting key,value pairs in 'x' is replaced with the ones in 'y'.
I want the conflicting key,value pairs to contain largest data present in x or y.
For example:
x = {1:'small_data',2:{1:'random laaaarge data',2:'random small data'}}
y = {1:'laaaaaarge_data',2:{1:'random small data',2:'random laaaarge data'}}
Now
z = {**x,**y}
# DATA in z should be {1:'laaaaaarge_data',2:{1:'random laaaarge data',2:'random laaaarge data'}}
NOTE: It should work for any arbitrary data that has a size.
Is this even possible? If so, what is the most pythonic way to do it.
Why not something like:
def merge_dicts(dict_list):
merged = {}
for sub_dict in dict_list:
for key, value in sub_dict.items():
if key in merged:
merged[key] = get_biggest(merged[key], value)
else:
merged[key] = value
return merged
def get_biggest(*items):
# function for comparing your 2 items based on your "size" requirements
return biggest

How to predict key from its value in python? [duplicate]

I made a function which will look up ages in a Dictionary and show the matching name:
dictionary = {'george' : 16, 'amber' : 19}
search_age = raw_input("Provide age")
for age in dictionary.values():
if age == search_age:
name = dictionary[age]
print name
I know how to compare and find the age I just don't know how to show the name of the person. Additionally, I am getting a KeyError because of line 5. I know it's not correct but I can't figure out how to make it search backwards.
mydict = {'george': 16, 'amber': 19}
print mydict.keys()[mydict.values().index(16)] # Prints george
Or in Python 3.x:
mydict = {'george': 16, 'amber': 19}
print(list(mydict.keys())[list(mydict.values()).index(16)]) # Prints george
Basically, it separates the dictionary's values in a list, finds the position of the value you have, and gets the key at that position.
More about keys() and .values() in Python 3: How can I get list of values from dict?
There is none. dict is not intended to be used this way.
dictionary = {'george': 16, 'amber': 19}
search_age = input("Provide age")
for name, age in dictionary.items(): # for name, age in dictionary.iteritems(): (for Python 2.x)
if age == search_age:
print(name)
If you want both the name and the age, you should be using .items() which gives you key (key, value) tuples:
for name, age in mydict.items():
if age == search_age:
print name
You can unpack the tuple into two separate variables right in the for loop, then match the age.
You should also consider reversing the dictionary if you're generally going to be looking up by age, and no two people have the same age:
{16: 'george', 19: 'amber'}
so you can look up the name for an age by just doing
mydict[search_age]
I've been calling it mydict instead of list because list is the name of a built-in type, and you shouldn't use that name for anything else.
You can even get a list of all people with a given age in one line:
[name for name, age in mydict.items() if age == search_age]
or if there is only one person with each age:
next((name for name, age in mydict.items() if age == search_age), None)
which will just give you None if there isn't anyone with that age.
Finally, if the dict is long and you're on Python 2, you should consider using .iteritems() instead of .items() as Cat Plus Plus did in his answer, since it doesn't need to make a copy of the list.
I thought it would be interesting to point out which methods are the quickest, and in what scenario:
Here's some tests I ran (on a 2012 MacBook Pro)
def method1(dict, search_age):
for name, age in dict.iteritems():
if age == search_age:
return name
def method2(dict, search_age):
return [name for name,age in dict.iteritems() if age == search_age]
def method3(dict, search_age):
return dict.keys()[dict.values().index(search_age)]
Results from profile.run() on each method 100,000 times:
Method 1:
>>> profile.run("for i in range(0,100000): method1(dict, 16)")
200004 function calls in 1.173 seconds
Method 2:
>>> profile.run("for i in range(0,100000): method2(dict, 16)")
200004 function calls in 1.222 seconds
Method 3:
>>> profile.run("for i in range(0,100000): method3(dict, 16)")
400004 function calls in 2.125 seconds
So this shows that for a small dict, method 1 is the quickest. This is most likely because it returns the first match, as opposed to all of the matches like method 2 (see note below).
Interestingly, performing the same tests on a dict I have with 2700 entries, I get quite different results (this time run 10,000 times):
Method 1:
>>> profile.run("for i in range(0,10000): method1(UIC_CRS,'7088380')")
20004 function calls in 2.928 seconds
Method 2:
>>> profile.run("for i in range(0,10000): method2(UIC_CRS,'7088380')")
20004 function calls in 3.872 seconds
Method 3:
>>> profile.run("for i in range(0,10000): method3(UIC_CRS,'7088380')")
40004 function calls in 1.176 seconds
So here, method 3 is much faster. Just goes to show the size of your dict will affect which method you choose.
Notes:
Method 2 returns a list of all names, whereas methods 1 and 3 return only the first match.
I have not considered memory usage. I'm not sure if method 3 creates 2 extra lists (keys() and values()) and stores them in memory.
one line version: (i is an old dictionary, p is a reversed dictionary)
explanation : i.keys() and i.values() returns two lists with keys and values of the dictionary respectively. The zip function has the ability to tie together lists to produce a dictionary.
p = dict(zip(i.values(),i.keys()))
Warning : This will work only if the values are hashable and unique.
I found this answer very effective but not very easy to read for me.
To make it more clear you can invert the key and the value of a dictionary. This is make the keys values and the values keys, as seen here.
mydict = {'george':16,'amber':19}
res = dict((v,k) for k,v in mydict.iteritems())
print(res[16]) # Prints george
or for Python 3, (thanks #kkgarg)
mydict = {'george':16,'amber':19}
res = dict((v,k) for k,v in mydict.items())
print(res[16]) # Prints george
Also
print(res.get(16)) # Prints george
which is essentially the same that this other answer.
a = {'a':1,'b':2,'c':3}
{v:k for k, v in a.items()}[1]
or better
{k:v for k, v in a.items() if v == 1}
key = next((k for k in my_dict if my_dict[k] == val), None)
Try this one-liner to reverse a dictionary:
reversed_dictionary = dict(map(reversed, dictionary.items()))
If you want to find the key by the value, you can use a dictionary comprehension to create a lookup dictionary and then use that to find the key from the value.
lookup = {value: key for key, value in self.data}
lookup[value]
we can get the Key of dict by :
def getKey(dct,value):
return [key for key in dct if (dct[key] == value)]
You can get key by using dict.keys(), dict.values() and list.index() methods, see code samples below:
names_dict = {'george':16,'amber':19}
search_age = int(raw_input("Provide age"))
key = names_dict.keys()[names_dict.values().index(search_age)]
Here is my take on this problem. :)
I have just started learning Python, so I call this:
"The Understandable for beginners" solution.
#Code without comments.
list1 = {'george':16,'amber':19, 'Garry':19}
search_age = raw_input("Provide age: ")
print
search_age = int(search_age)
listByAge = {}
for name, age in list1.items():
if age == search_age:
age = str(age)
results = name + " " +age
print results
age2 = int(age)
listByAge[name] = listByAge.get(name,0)+age2
print
print listByAge
.
#Code with comments.
#I've added another name with the same age to the list.
list1 = {'george':16,'amber':19, 'Garry':19}
#Original code.
search_age = raw_input("Provide age: ")
print
#Because raw_input gives a string, we need to convert it to int,
#so we can search the dictionary list with it.
search_age = int(search_age)
#Here we define another empty dictionary, to store the results in a more
#permanent way.
listByAge = {}
#We use double variable iteration, so we get both the name and age
#on each run of the loop.
for name, age in list1.items():
#Here we check if the User Defined age = the age parameter
#for this run of the loop.
if age == search_age:
#Here we convert Age back to string, because we will concatenate it
#with the person's name.
age = str(age)
#Here we concatenate.
results = name + " " +age
#If you want just the names and ages displayed you can delete
#the code after "print results". If you want them stored, don't...
print results
#Here we create a second variable that uses the value of
#the age for the current person in the list.
#For example if "Anna" is "10", age2 = 10,
#integer value which we can use in addition.
age2 = int(age)
#Here we use the method that checks or creates values in dictionaries.
#We create a new entry for each name that matches the User Defined Age
#with default value of 0, and then we add the value from age2.
listByAge[name] = listByAge.get(name,0)+age2
#Here we print the new dictionary with the users with User Defined Age.
print
print listByAge
.
#Results
Running: *\test.py (Thu Jun 06 05:10:02 2013)
Provide age: 19
amber 19
Garry 19
{'amber': 19, 'Garry': 19}
Execution Successful!
get_key = lambda v, d: next(k for k in d if d[k] is v)
Consider using Pandas. As stated in William McKinney's "Python for Data Analysis'
Another way to think about a Series is as a fixed-length, ordered
dict, as it is a mapping of index values to data values. It can be
used in many contexts where you might use a dict.
import pandas as pd
list = {'george':16,'amber':19}
lookup_list = pd.Series(list)
To query your series do the following:
lookup_list[lookup_list.values == 19]
Which yields:
Out[1]:
amber 19
dtype: int64
If you need to do anything else with the output transforming the
answer into a list might be useful:
answer = lookup_list[lookup_list.values == 19].index
answer = pd.Index.tolist(answer)
d= {'george':16,'amber':19}
dict((v,k) for k,v in d.items()).get(16)
The output is as follows:
-> prints george
Here, recover_key takes dictionary and value to find in dictionary. We then loop over the keys in dictionary and make a comparison with that of value and return that particular key.
def recover_key(dicty,value):
for a_key in dicty.keys():
if (dicty[a_key] == value):
return a_key
One line solution using list comprehension, which returns multiple keys if the value is possibly present multiple times.
[key for key,value in mydict.items() if value == 16]
for name in mydict:
if mydict[name] == search_age:
print(name)
#or do something else with it.
#if in a function append to a temporary list,
#then after the loop return the list
my_dict = {'A': 19, 'B': 28, 'carson': 28}
search_age = 28
take only one
name = next((name for name, age in my_dict.items() if age == search_age), None)
print(name) # 'B'
get multiple data
name_list = [name for name, age in filter(lambda item: item[1] == search_age, my_dict.items())]
print(name_list) # ['B', 'carson']
I glimpsed all answers and none mentioned simply using list comprehension?
This Pythonic one-line solution can return all keys for any number of given values (tested in Python 3.9.1):
>>> dictionary = {'george' : 16, 'amber' : 19, 'frank': 19}
>>>
>>> age = 19
>>> name = [k for k in dictionary.keys() if dictionary[k] == age]; name
['george', 'frank']
>>>
>>> age = (16, 19)
>>> name = [k for k in dictionary.keys() if dictionary[k] in age]; name
['george', 'amber', 'frank']
>>>
>>> age = (22, 25)
>>> name = [k for k in dictionary.keys() if dictionary[k] in age]; name
[]
it's answered, but it could be done with a fancy 'map/reduce' use, e.g.:
def find_key(value, dictionary):
return reduce(lambda x, y: x if x is not None else y,
map(lambda x: x[0] if x[1] == value else None,
dictionary.iteritems()))
I tried to read as many solutions as I can to prevent giving duplicate answer. However, if you are working on a dictionary which values are contained in lists and if you want to get keys that have a particular element you could do this:
d = {'Adams': [18, 29, 30],
'Allen': [9, 27],
'Anderson': [24, 26],
'Bailey': [7, 30],
'Baker': [31, 7, 10, 19],
'Barnes': [22, 31, 10, 21],
'Bell': [2, 24, 17, 26]}
Now lets find names that have 24 in their values.
for key in d.keys():
if 24 in d[key]:
print(key)
This would work with multiple values as well.
Just my answer in lambda and filter.
filter( lambda x, dictionary=dictionary, search_age=int(search_age): dictionary[x] == search_age , dictionary )
already been answered, but since several people mentioned reversing the dictionary, here's how you do it in one line (assuming 1:1 mapping) and some various perf data:
python 2.6:
reversedict = dict([(value, key) for key, value in mydict.iteritems()])
2.7+:
reversedict = {value:key for key, value in mydict.iteritems()}
if you think it's not 1:1, you can still create a reasonable reverse mapping with a couple lines:
reversedict = defaultdict(list)
[reversedict[value].append(key) for key, value in mydict.iteritems()]
how slow is this: slower than a simple search, but not nearly as slow as you'd think - on a 'straight' 100000 entry dictionary, a 'fast' search (i.e. looking for a value that should be early in the keys) was about 10x faster than reversing the entire dictionary, and a 'slow' search (towards the end) about 4-5x faster. So after at most about 10 lookups, it's paid for itself.
the second version (with lists per item) takes about 2.5x as long as the simple version.
largedict = dict((x,x) for x in range(100000))
# Should be slow, has to search 90000 entries before it finds it
In [26]: %timeit largedict.keys()[largedict.values().index(90000)]
100 loops, best of 3: 4.81 ms per loop
# Should be fast, has to only search 9 entries to find it.
In [27]: %timeit largedict.keys()[largedict.values().index(9)]
100 loops, best of 3: 2.94 ms per loop
# How about using iterkeys() instead of keys()?
# These are faster, because you don't have to create the entire keys array.
# You DO have to create the entire values array - more on that later.
In [31]: %timeit islice(largedict.iterkeys(), largedict.values().index(90000))
100 loops, best of 3: 3.38 ms per loop
In [32]: %timeit islice(largedict.iterkeys(), largedict.values().index(9))
1000 loops, best of 3: 1.48 ms per loop
In [24]: %timeit reversedict = dict([(value, key) for key, value in largedict.iteritems()])
10 loops, best of 3: 22.9 ms per loop
In [23]: %%timeit
....: reversedict = defaultdict(list)
....: [reversedict[value].append(key) for key, value in largedict.iteritems()]
....:
10 loops, best of 3: 53.6 ms per loop
Also had some interesting results with ifilter. Theoretically, ifilter should be faster, in that we can use itervalues() and possibly not have to create/go through the entire values list. In practice, the results were... odd...
In [72]: %%timeit
....: myf = ifilter(lambda x: x[1] == 90000, largedict.iteritems())
....: myf.next()[0]
....:
100 loops, best of 3: 15.1 ms per loop
In [73]: %%timeit
....: myf = ifilter(lambda x: x[1] == 9, largedict.iteritems())
....: myf.next()[0]
....:
100000 loops, best of 3: 2.36 us per loop
So, for small offsets, it was dramatically faster than any previous version (2.36 *u*S vs. a minimum of 1.48 *m*S for previous cases). However, for large offsets near the end of the list, it was dramatically slower (15.1ms vs. the same 1.48mS). The small savings at the low end is not worth the cost at the high end, imho.
Cat Plus Plus mentioned that this isn't how a dictionary is intended to be used. Here's why:
The definition of a dictionary is analogous to that of a mapping in mathematics. In this case, a dict is a mapping of K (the set of keys) to V (the values) - but not vice versa. If you dereference a dict, you expect to get exactly one value returned. But, it is perfectly legal for different keys to map onto the same value, e.g.:
d = { k1 : v1, k2 : v2, k3 : v1}
When you look up a key by it's corresponding value, you're essentially inverting the dictionary. But a mapping isn't necessarily invertible! In this example, asking for the key corresponding to v1 could yield k1 or k3. Should you return both? Just the first one found? That's why indexof() is undefined for dictionaries.
If you know your data, you could do this. But an API can't assume that an arbitrary dictionary is invertible, hence the lack of such an operation.
here is my take on it. This is good for displaying multiple results just in case you need one. So I added the list as well
myList = {'george':16,'amber':19, 'rachel':19,
'david':15 } #Setting the dictionary
result=[] #Making ready of the result list
search_age = int(input('Enter age '))
for keywords in myList.keys():
if myList[keywords] ==search_age:
result.append(keywords) #This part, we are making list of results
for res in result: #We are now printing the results
print(res)
And that's it...
There is no easy way to find a key in a list by 'looking up' the value. However, if you know the value, iterating through the keys, you can look up values in the dictionary by the element. If D[element] where D is a dictionary object, is equal to the key you're trying to look up, you can execute some code.
D = {'Ali': 20, 'Marina': 12, 'George':16}
age = int(input('enter age:\t'))
for element in D.keys():
if D[element] == age:
print(element)
You need to use a dictionary and reverse of that dictionary. It means you need another data structure. If you are in python 3, use enum module but if you are using python 2.7 use enum34 which is back ported for python 2.
Example:
from enum import Enum
class Color(Enum):
red = 1
green = 2
blue = 3
>>> print(Color.red)
Color.red
>>> print(repr(Color.red))
<color.red: 1="">
>>> type(Color.red)
<enum 'color'="">
>>> isinstance(Color.green, Color)
True
>>> member = Color.red
>>> member.name
'red'
>>> member.value
1
def get_Value(dic,value):
for name in dic:
if dic[name] == value:
del dic[name]
return name

python: max value in a dictionary with 2 keys

I have a dictionary D set up as D={('a','b'):['1000','5','.3'], ('c','d'):['2000','8','-.8']} where ('a','b') and ('c','d') are the keys. I am having trouble finding the maximum of the first values in the lists. So in using max(D) I need it to return ('c','d'). Keep in mind my list is hundreds of pairings. I just need to have the max() function be able to recognize the first value '2000' and '1000' and find the maximum of those. Any help or suggestions would be greatly appreciated.
python max function takes a key that you can use to define your function or lambda.
D={('a','b'):['1000','5','.3'], ('c','d'):['2000','8','-.8']}
res=max(D.items(), key=lambda k: int(k[1][0]))
print(res[0])
output:
('c', 'd')
Explanation:
In the code above, k will be the nth item/value pair as a tuple of your dictionary D. For first item k is (('a','b'),['1000','5','.3']). Then int(k[1][0]) returns 1000. We need to convert to int otherwise max will do string comparison.
Online link for above code: http://ideone.com/qmZvs8
You need to iterate through the dictionary, converting the first value's item to an int, and saving them for later:
first_values = []
for val in D.values():
first_values.append(int(val[0]))
print(max(first_values))
Taking your question literally, the max of '2000', '1000', etc is produced as follows
mx = max(val[0] for val in D.values())
or
from operator import itemgetter
mx = max(D.values(), key=itemgetter(0))[0
or
mx = max(D.values(), key=lambda val: val[0])[0]
Interpreting your question to mean max of 2000, 1000, etc (int('2000'), int('1000')
mx = max(int(val[0]) for val in D.values())
Interpreting your question a bit more, to include wanting the key with the max first value:
mxpair = max(d.items(), key=lambda item: int(item[1][0]))
key, mx = mxpair[0], mxpair[1][0])

How to retrieve the max key and max value from a dictionary?

a = ['also', 'akin', 'akee','ague', 'aero', 'anes','here','beer','bute', 'byre', 'came', 'case', 'doze', 'down', 'drek', 'drew', 'dyes', 'fret', 'freo']
i = 'e'#i is user guess input
dic = {}
for item in a:
key = ''
for chr in item:
if chr == i:
key += i
else:
key += '-'
if key not in dic:
dic[key] = []
dic[key].append(item)
print(dic)
c = max(k for k, v in dic.items())
d = max(v for k, v in dic.items())
print('\nmax key:',c)
print('\nmax value:',d)
Output:
{'---e': ['ague', 'bute', 'byre', 'came', 'case', 'doze'], '--ee': ['akee'], '----': ['also', 'akin', 'down'], '-e-e': ['here'], '-ee-': ['beer'], '--e-': ['anes', 'drek', 'drew', 'dyes', 'fret', 'freo'], '-e--': ['aero']}
max key: -ee-
max value: ['here']
In the above example, a is a list of words. When the user guess a letter, for example 'e', the program iterates through each word in the list. Replace any letter that is not 'e' to a dash '-'.
I tried to map that result into a dictionary to keep track of the each group of words that where letter 'e' occurs in the same position.
Now, i want to retrieve the group of words(or key) with the largest number of words. Judging by the output, i'm not doing that because key'-e--' has the largest number of words.
I've also tried
max(dic.keys())
max(dic)
dic.get(max(dic.keys()))
Am i not fully understand the concept of max key and values for a dictionary?
Please suggest how i can fix this.
Thanks
In your question, the notion of max means being associated with the largest list., or being the largest list
max(dic.keys(), key=lambda x: len(dic[x]))
Will give you the maximum of dic's keys
Also,
sorted(dic.items(), key=lambda x:len(x[1]), reverse=True)
(in this example, lambda (x, y): len(y) works in python 2, not sure about python 3)
Will output a list of key, value tuples sorted by number of matches:
[('---e', ['ague', 'bute', 'byre', 'came', 'case', 'doze']), ('--e-', ['anes', 'drek', 'drew', 'dyes', 'fret', 'freo']), ('----', ['also', 'akin', 'down']), ('-e-e', ['here']), ('--ee', ['akee']), ('-e--', ['aero']), ('-ee-', ['beer'])]
Edit, no lambda
Without using a lambda, you'd be using a regular function:
def myMax(value_tuple):
key, value = value_tuple
return len(value)
and using it like so:
max(dic.items(), key=myMax)
Retrieve max key:
max(MyDictionary.keys(), key=type).
Retrieve max value:
max(MyDictionary.values(), key=type)
Replace type with the key type in both cases. i.e int
Hope it helps.

Resources