Python printing single key/value pairs from a dict [duplicate] - python

This question already has answers here:
Get key by value in dictionary
(43 answers)
Closed 7 years ago.
Say I have the following code that makes a dict:
x = 0
myHash = {}
name = ["Max","Fred","Alice","Bobby"]
while x <= 3:
myHash[name[x]] = x
x += 1
l = sorted(myHash.values(), reverse=True)
largestNum = l[0]
# print myHash.getKeyFromValue(largestNum)
Is it possible to easily get the key that is paired to my largestNum variable without looping through the entire dict? Something like the pseudo code in the line at the bottom.
Note: I don't want to get a value from a key. I want the reverse of that.

Don't just sort the values. Sort the items by their values, and get the key for free.
from operator import itemgetter
l = sorted(myHash.items(), key=itemgetter(1), reverse=True)
largestKey, largestNum = l[0]
Note: If you only want the largest value, not the rest of the sort results, you can save some work and skip the full sorted work (reducing work from O(n log n) to O(n)):
largestKey, largestNum = max(myHash.items(), key=itemgetter(1))
For the general case of inverting a dict, if the values are unique, it's trivial to create a reversed mapping:
invert_dict = {v: k for k, v in orig_dict.items()}
If the values aren't unique, and you want to find all keys corresponding to a single value with a single lookup, you'd invert to a multi-dict:
from collections import defaultdict
invert_dict = defaultdict(set)
for k, v in orig_dict.items():
invert_dict[v].add(k)
# Optionally convert back to regular dict to avoid lookup auto-vivification in the future:
# invert_dict = dict(invert_dict)

Related

Python dictionary comprehension to group together equal keys

I have a code snippit that groups together equal keys from a list of dicts and adds the dict with equal ObjectID to a list under that key.
Code bellow works, but I am trying to convert it to a Dictionary comprehension
group togheter subblocks if they have equal ObjectID
output = {}
subblkDBF : list[dict]
for row in subblkDBF:
if row["OBJECTID"] not in output:
output[row["OBJECTID"]] = []
output[row["OBJECTID"]].append(row)
Using a comprehension is possible, but likely inefficient in this case, since you need to (a) check if a key is in the dictionary at every iteration, and (b) append to, rather than set the value. You can, however, eliminate some of the boilerplate using collections.defaultdict:
output = defaultdict(list)
for row in subblkDBF:
output[row['OBJECTID']].append(row)
The problem with using a comprehension is that if really want a one-liner, you have to nest a list comprehension that traverses the entire list multiple times (once for each key):
{k: [d for d in subblkDBF if d['OBJECTID'] == k] for k in set(d['OBJECTID'] for d in subblkDBF)}
Iterating over subblkDBF in both the inner and outer loop leads to O(n^2) complexity, which is pointless, especially given how illegible the result is.
As the other answer shows, these problems go away if you're willing to sort the list first, or better yet, if it is already sorted.
If rows are sorted by Object ID (or all rows with equal Object ID are at least next to each other, no matter the overall order of those IDs) you could write a neat dict comprehension using itertools.groupby:
from itertools import groupby
from operator import itemgetter
output = {k: list(g) for k, g in groupby(subblkDBF, key=itemgetter("OBJECTID"))}
However, if this is not the case, you'd have to sort by the same key first, making this a lot less neat, and less efficient than above or the loop (O(nlogn) instead of O(n)).
key = itemgetter("OBJECTID")
output = {k: list(g) for k, g in groupby(sorted(subblkDBF, key=key), key=key)}
You can adding an else block to safe on time n slightly improve perfomrance a little:
output = {}
subblkDBF : list[dict]
for row in subblkDBF:
if row["OBJECTID"] not in output:
output[row["OBJECTID"]] = [row]
else:
output[row["OBJECTID"]].append(row)

How to unpack dict with one key-value pair to two variables more elegantly? [duplicate]

This question already has answers here:
How to extract dictionary single key-value pair in variables
(11 answers)
Closed 3 years ago.
Currently, I'm using this:
d = {'a': 'xyz'}
k, v = list(*d.items())
The starred expression is required here, as omitting it causes the list function/constructor to return a list with a single tuple, which contains the key and value.
However, I was wondering if there were a better way to do it.
Keep nesting:
>>> d = {'a': 'xyz'}
>>> ((k,v),) = d.items()
>>> k
'a'
>>> v
'xyz'
Or equivalently:
>>> (k,v), = d.items()
>>> k
'a'
>>> v
'xyz'
>>>
Not sure which I prefer, the last one might be a bit difficult to read if I was glancing at it.
Note, the advantage here is that it is non-destructive and fails if the dict has more than one key-value pair.
Since dict items do not support indexed access, you might resort to the following non-mutating retrieval of the first (and only) item:
k, v = next(iter(d.items()))
This has the advantage of not only working for dicts of any size, but remaining an O(1) operation which other solutions that unpack the items or convert them to a list would not.
If you don't mind the dictionary getting altered, this'll do:
k, v = d.popitem()

how to sort python objects using key of python list [duplicate]

This question already has answers here:
Nested lambda statements when sorting lists
(8 answers)
Closed 4 years ago.
I have a list of strings in the below format:
['b-3','a-2','c-4','d-2']
Need to sort in such a way that list is sorted by the number (following -). If the numbers are equal, the string needs to be sorted in alphabetical order. Output should be
['a-2','d-2','b-3','c-4']
I can easily achieve in JAVA using comparator / comparable. How to achieve this by writing the function in python.
list.sort(key= )
import sys
from collections import Counter, OrderedDict
def sortfunc(item):
key,value = item.split('-')
return value
if __name__ == "__main__":
s = input().strip()
c = Counter(s)
lst = []
for key in c:
lst.append(key+'-'+str(c[key]))
lst.sort(key=lambda x :sortfunc(x), reverse=True)
print(lst)
gives the output as:
['b-3', 'c-2', 'a-2', 'e-1', 'd-1']
Now, I need help to enhance sortFunc is such as way - if the count of characters are equal, then the string needs to be sorted in alphabetical order.
This is one way.
lst = ['b-3', 'a-2', 'c-4', 'd-2']
res = sorted(lst, key=lambda x: (lambda y: (int(y[1]), y[0]))(x.split('-')))
# ['a-2', 'd-2', 'b-3', 'c-4']
Explanation
Use sorted with key argument and a custom lambda function.
Tuple comparisons are performed in order of tuple index.
Remember to convert the first tuple value to int for integer comparison.
You cannot use x.split('-')[::-1] directly as you need to convert one of the values to int.

Copying first n items of a dictionary into another dictionary

This is a simple question but I am unable to code this in python. I want to copy first n items ( supposedly 100 ) i.e both the values and keys into another empty dictionary. I'll give a more clear picture of this. I created a dictionary and sorted it using OrderedDict. My code for sorting it is :
ordP = OrderedDict(reversed(sorted(wcP.items(), key=lambda t: t[1])))
Here ordP is the ordered dictionary I got. This is in descending order. And my original dictionary is wcP. I want to put the first 100 values of ordP i.e the first 100 maximum values of ordP ( sorted according to the keys ) in a new dictionary.
Dictionaries aren't ordered, but if you just want a random selection:
new_values = dict(your_values.items()[:n])
Or, for those obsessed with laziness:
import itertools
new_values = dict(itertools.islice(your_values.iteritems(), n))
If there's a particular sort you want to impose, define a key function that takes the key and value. People usually do lambdas, but there's no reason you can't use a full function.
def example_key_func((key, value)):
return key * value
new_dict = dict(sorted(your_values.items(), key=example_key_func)[:n])
n = 100
assert len(d.keys()) >= n
dic100 = {k:v for k,v in list(d.items())[:n]}

Basic way to find largest values in dictionary [duplicate]

This question already has answers here:
finding top k largest keys in a dictionary python
(6 answers)
Closed 7 years ago.
Let's say I have a dictionary. I want to find the 4 keys with the highest values. I want to do this in a very basic way. I'm not that advanced with CS. I just want to iterate over the dictionary. Or how should I do this? I realize it cannot be that challenging. I don't want to use heapq. How can I do this?
I think the most pythonic way is:
sorted(d, key=d.get, reverse=True)[:4]
You should be using a collections.Counter object instead.
c = collections.Counter(original_dict)
c.most_common(4)
If you just want the keys, then:
[k for k, v in c.most_common(4)]
For reference on how it is implemented, check the source code here.
Sort by the values and then slice. The sorted function takes a key function.
items_by_value = sorted(d.items(), key=lambda (k, v): v)
keys = [k for k, v in items_by_value[-4:]]
Good question.
Assuming d is the dictionary, and if you don't care what order the keys are in, you could use something like the following:
keys = [v[0] for v in sorted(d.items(), key=lambda v: v[1])[-4:]]
For huge dictionaries, it would be a more efficient to use:
keys = [v[0] for v in sorted(d.items(), key=operator.itemgetter(1))[-4:]]
The [-4:] means the last four entries. In both cases, if you want the keys in the same order as their corresponding highest values, use [-1:-5:-1] instead, which are the last four entries in reverse order.

Categories

Resources