Iterate through dictionary by indexes - python-3.x

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]}")

Related

Convert elements in ONE list to keys and values in a dictionary

I'm looking for a way to convert a list to a dictionary as shown below. Is this possible? Thanks in advance.
list = ["1/a", "2/b", "3/c"]
dict = {"1": "a", "2": "b", "3": "c"}
Of course it is possible.
First, you can split an element of the list with e.split("/"), which will give a list for example splitted = ["1", "a"].
You can assign the first element to the key and the second to the value:
k = splitted[0]
v = splitted[1]
or another way to express that:
k,v = splitted
Then you can iterate over your list to build your dict, so if we wrap this up (you should not call a list list because list is a type and an already existing identifier:
d = {}
for e in elements:
k,v = e.split("/")
d[k] = v
You can also do that in one line with a dict comprehension:
d = {k:v for k,v in [e.split("/") for e in elements]}
Yes you can.
If you want to have everything after the '/' (i.e. 2nd char), you can do:
dict = {c[0]:c[2:] for c in list}
If you want to have everything after the '/' (but may not be the 2nd char), you can do:
dict = {c[0]:c.split('/')[1] for c in list}
It really dependes on the input you have and what output you want
You can do like this.
lista = ["1/a", "2/b", "3/c"]
new_dict = {}
for val in lista:
new_dict.update({val[0]:val[2]})
print(new_dict)
Try this
list = ["1as/aasc", "2sa/bef", "3edc/cadeef"]
dict = {i.split('/')[0]:i.split('/')[1] for i in list}
Answer will be
{'1as': 'aasc', '2sa': 'bef', '3edc': 'cadeef'}
I have given a different test case. Hope this will answer your question.

How to get the innermost value among dictionaries at one go?

Here is my dictionary:
my_dict = {'00.Life': help}
help ={'A.Death':['dying','dead','mourir','pass away']}
I have one dictionary inside the other one.
How to get the innermost value at one go?
I hope I could just input 'dying'(one of the elements in the list) to get ['dying','dead','mourir','pass away'] list.
How to do that?
You can't do it "at one go" using your existing data structure. You will have to either iterate all the values, or construct a reversed, lookup dictionary first. For example:
>>> my_help ={'A.Death':['dying','dead','mourir','pass away']}
>>> my_dict = {'00.Life': my_help}
>>> lookup_dict = {k: v for v in my_dict["00.Life"].values() for k in v}
>>> lookup_dict["dying"]
['dying', 'dead', 'mourir', 'pass away']

Best way to Sort Python Dictionary by number of same Values

I have a dictionary as follows:
input = {1:'a', 2:'b', 3:'c', 4:'b', 5:'c', 6:'b'}
a - 1 time
b - 3 times
c - 2 times
I want to sort the dictionary in such a way that the value which repeats maximum times will come at fist followed by the value which repeats second most times and so on...
Desired Output
output = {1:'b', 2:'c', 3:'a'}
Please help
Thanks in advance
First of all, you need to realize you do not even care about input dict keys, only about input dict values.
real_input = input.values()
Second of all, you need to count occurences:
counted_items = collections.Counter(real_input)
Third of all, you want to iterate over them in order from most common to least common. .most_common() returns list of (key, count) tuples in expected order.
most_common_in_order = counted_items.most_common()
After that you want to convert that list to dict, with consecutive inegers as keys
result = {i: v for i, (v, _) in zip(itertools.count(1), most_common_in_order)}
Or, in concise form:
result = {i: v for i, (v, _) in zip(itertools.count(1),
collections.Counter(input.values()).most_common())}
Note that dictionaries are inherently not ordered, so actual order is implementation detail, and it's not guaranteed.
from collections import Counter
input = {1: 'a', 2: 'b', 3: 'c', 4: 'b', 5: 'c', 6: 'b'}
output = {index: value for index, (value, _)
in enumerate(Counter(input.values()).most_common(),
start=1)}
print(output)
Edited for Python 3 compatibility.
from collections import Counter
i = {1:'a', 2:'b', 3:'c', 4:'b', 5:'c', 6:'b'}
print (Counter(i.values()))
#Output
Counter({'b': 3, 'c': 2, 'a': 1})

How to get keys from nested dictionary of arbitrary length in Python

I have a dictionary object in python. Let's call it as dict. This object could contain another dictionary which may in turn contain another dictionary and so on.
dict = { 'k': v, 'k1': v1, 'dict2':{'k3': v3, 'k4':v4} , 'dict3':{'k5':v5, dict4:{'k6':v6}}}
This is just an example. Length of outermost dictionary could be anything. I want to extract keys from such dictionary object in following two ways :
get list of only keys.
[k,k1,k2,k3,k4,k5,k6]
get list of keys and its parent associated dictionary so something like this :
outer_dict_keys = [k ,dict2, dict3]
dict2_keys = [k3,k4]
dict3_keys = [k5, dict4]
dict4_keys = [k6]
Outermost dictionary dict length is always changing so I can not hard code anything.
What is best way to achieve above result ?
Use a mix of iteration and tail recursion. After quoting undefined names, making spacing uniform, and removing 'k2' from the first result, I came up with the code below. (Written and tested for 3.4, it should run on any 3.x and might on 2.7.) A key thing to remember is that the iteration order of dicts is essentially random, and varies with each run. Recursion as done here visit sub-dicts in depth-first rather than breadth-first order. For dict0, both are the same, But if dict4 were nested in dict2 rather than dict3, they would not be.
dict0 = {'k0': 0, 'k1': 1, 'dict2':{'k3': 3, 'k4': 4},
'dict3':{'k5': 5, 'dict4':{'k6': 6}}}
def keys(dic, klist=[]):
subdics = []
for key in sorted(dic):
val = dic[key]
if isinstance(val, dict):
subdics.append(val)
else:
klist.append(key)
for subdict in subdics:
keys(subdict, klist)
return klist
result = keys(dict0)
print(result, '\n', result == ['k0','k1','k3','k4','k5','k6'])
def keylines(dic, name='outer_dict', lines=[]):
vals = []
subdics = []
for key in sorted(dic):
val = dic[key]
if isinstance(val, dict):
subdics.append((key,val))
else:
vals.append(key)
vals.extend(pair[0] for pair in subdics)
lines.append('{}_keys = {}'.format(name, vals))
for subdict in subdics:
keylines(subdict[1], subdict[0], lines)
return lines
result = keylines(dict0)
for line in result:
print(line,)
print()
expect = [
"outer_dict_keys = ['k0', 'k1', 'dict2', 'dict3']",
"dict2_keys = ['k3', 'k4']",
"dict3_keys = ['k5', 'dict4']",
"dict4_keys = ['k6']"]
for actual, want in zip(result, expect):
if actual != want:
print(want)
for i, (c1, c2) in enumerate(zip(actual, want)):
if c1 != c2:
print(i, c1, c2)

Is it possible to delete keys meeting some criterion using a simple iteration in Python3?

Suppose we have a dict d={"key1":-1,"key2":-2,"key3":3,"key4":0,"key5":-7,"key6":1,...} in python3. Now I want to delete keys whose value is negative, e.g.,"key1":-1,"key2":-2,etc. I tried to write a code like this:
for k in d:
if d[k]<0:
del d[k]
But I received error saying "RuntimeError: dictionary changed size during iteration". From this message, it seems that it is not possible to delete keys of a dictionary meeting some criterion using a simple iteration, so at the moment, I have to save the keys to be deleted in a list, then write another iteration to remove them from d. My question is: is it really impossible to remove some of keys using a single iteration? If it's possible, could you please give a sample code of Python3 that can remove keys meeting some criterion using a simple iteration in Python3? Thank you.
Method #1: use a dictionary comprehension. This doesn't delete so much as replace, but gets you to the same d.
>>> d = {"key1":-1,"key2":-2,"key3":3,"key4":0,"key5":-7}
>>> d = {k: v for k,v in d.items() if v >= 0}
>>> d
{'key3': 3, 'key4': 0}
Method #2: iterate over an independent copy of the keys:
>>> d = {"key1":-1,"key2":-2,"key3":3,"key4":0,"key5":-7}
>>> for k in set(d):
... if d[k] < 0:
... del d[k]
...
>>> d
{'key3': 3, 'key4': 0}
Iterate over the keys instead of the dict:
for k in d.keys():
if d[k]<0:
del d[k]
For this to work in Python 3.X, keys() returns an iterator, so you need to use the following first line:
for k in list(d.keys()):

Resources