Iterate over X dictionary items in Python - python

How can I iterate over only X number of dictionary items? I can do it using the following bulky way, but I am sure Python allows a more elegant way.
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
x = 0
for key in d:
if x == 3:
break
print key
x += 1

If you want a random sample of X values from a dictionary you can use random.sample on the dictionary's keys:
from random import sample
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
X = 3
for key in sample(d, X):
print key, d[key]
And get output for example:
e 5
c 3
b 2

Related

Adding to a dictionary based on key and value from lists?

I have a dictionary defined as:
letters = {'a': 2, 'b': 1, 'c': 5}
I want to add values to this dictionary based on two lists: one which contains the keys and another which contains the values.
key_list = [a, c]
value_list = [2, 5]
This should give the output:
{a: 4, b: 1, c: 10}
Any ideas on how I can accomplish this? I am new to working with the dictionary structure so I apologise if this is extremely simple.
Thanks.
You can zip the two lists and then add to the dictionary as so;
letters = {'a': 2, 'b': 1, 'c': 5}
key_list = ['a', 'c']
value_list = [2, 5]
for k,v in zip(key_list, value_list):
letters[k] = letters.get(k, 0) + v
Using the dictionary's get() method as above allows you to add letters that aren't already in the dictionary.
for i in range(len(key_list)):
letters[key_list[i]] += value_list[i]
You can simply add or modify values from a dictionary using the key
For example:
letters = {'a': 2, 'b':1 , 'c': 5}
letters['a'] += 2
letters['c'] += 5
print(letters)
output = {'a': 4, 'b': 1, 'c': 10}

how to convert a list to a default dictionary

I want to convert a list to a default dictionary to have a default value of 0 in case the key doesn't have any value (from the list).
list : order = ['a',1,'b',2,'c']
what I did using ZIP :
it = iter(order)
res_dict = dict(zip(it,it))
print(res_dict)
but it excludes c as a key, as the list doesn't have the next index after c.
Result I got : {'a': 1, 'b': 2}
Result i want : {'a': 1, 'b': 2, 'c': 0}
You might want to consider using itertools and .zip_longest().
For example:
import itertools
l = ['a',1,'b',2,'c']
d = dict(itertools.zip_longest(l[::2], l[1::2], fillvalue=0))
print(d)
Output:
{'a': 1, 'b': 2, 'c': 0}
This is working:
d = dict()
for i in range(len(order)):
if i%2==0 and i+1<len(order):
d[order[i]] =order[i+1]
elif i+2>(len(order)):
d[order[i]]=0
Result:
{'a': 1, 'b': 2, 'c': 0}
To solve the problem of two consequent keys you can use a custom function to split the list
def splitdefault(o):
i = 0
while i < len(o):
# there is a next element to check
if i + 1 < len(o):
# the next element is int
if isinstance(o[i + 1], int):
yield o[i], o[i + 1]
i += 2
else:
yield o[i], 0
i += 1
# i is the last element
else:
yield o[i], 0
i += 1
order = ["a", 1, "b", 2, "c", "d", 3, "e"]
for g in splitdefault(order):
print(g)
res_dict = dict(splitdefault(order))
print(res_dict)
Which produces
{'a': 1, 'b': 2, 'c': 0, 'd': 3, 'e': 0}
Cheers!

Nesting dictionary algorithm

Suppose I have the following dictionary:
{'a': 0, 'b': 1, 'c': 2, 'c.1': 3, 'd': 4, 'd.1': 5, 'd.1.2': 6}
I wish to write an algorithm which outputs the following:
{
"a": 0,
"b": 1,
"c": {
"c": 2,
"c.1": 3
},
"d":{
"d": 4,
"d.1": {
"d.1": 5,
"d.1.2": 6
}
}
}
Note how the names are repeated inside the dictionary. And some have variable level of nesting (eg. "d").
I was wondering how you would go about doing this, or if there is a python library for this? I know you'd have to use recursion for something like this, but my recursion skills are quite poor. Any thoughts would be highly appreciated.
You can use a recursive function for this or just a loop. The tricky part is wrapping existing values into dictionaries if further child nodes have to be added below them.
def nested(d):
res = {}
for key, val in d.items():
t = res
# descend deeper into the nested dict
for x in [key[:i] for i, c in enumerate(key) if c == "."]:
if x in t and not isinstance(t[x], dict):
# wrap leaf value into another dict
t[x] = {x: t[x]}
t = t.setdefault(x, {})
# add actual key to nested dict
if key in t:
# already exists, go one level deeper
t[key][key] = val
else:
t[key] = val
return res
Your example:
d = {'a': 0, 'b': 1, 'c': 2, 'c.1': 3, 'd': 4, 'd.1': 5, 'd.1.2': 6}
print(nested(d))
# {'a': 0,
# 'b': 1,
# 'c': {'c': 2, 'c.1': 3},
# 'd': {'d': 4, 'd.1': {'d.1': 5, 'd.1.2': 6}}}
Nesting dictionary algorithm ...
how you would go about doing this,
sort the dictionary items
group the result by index 0 of the keys (first item in the tuples)
iterate over the groups
if there are is than one item in a group make a key for the group and add the group items as the values.
Slightly shorter recursion approach with collections.defaultdict:
from collections import defaultdict
data = {'a': 0, 'b': 1, 'c': 2, 'c.1': 3, 'd': 4, 'd.1': 5, 'd.1.2': 6}
def group(d, p = []):
_d, r = defaultdict(list), {}
for n, [a, *b], c in d:
_d[a].append((n, b, c))
for a, b in _d.items():
if (k:=[i for i in b if i[1]]):
r['.'.join(p+[a])] = {**{i[0]:i[-1] for i in b if not i[1]}, **group(k, p+[a])}
else:
r[b[0][0]] = b[0][-1]
return r
print(group([(a, a.split('.'), b) for a, b in data.items()]))
Output:
{'a': 0, 'b': 1, 'c': {'c': 2, 'c.1': 3}, 'd': {'d': 4, 'd.1': {'d.1': 5, 'd.1.2': 6}}}

Add two dictionaries in python and subtract result from another

I have three dictionaries:
X = {'a':2, 'b':3,'e':4}
Y = {'c':3, 'b':4,'a':5, 'd':7}
Z = {'c':8, 'b':7,'a':9, 'e':10,'f':10}
I want to add elements of X and Y if they are present in both dicts and then subtract them from z i.e. Z-X+Y
How can I do that ?
expected result:
res = {'a':2,'b':0,'c':5,'d':7,'e':6,'f':10}
What I tried:
from collections import Counter
xy = Counter(X) + Counter(Y)
res = Counter(Z) - xy
which return:
Counter({'c': 5, 'a': 2, 'e': 6, 'f': 10})
as you can see b and d are missing from my attempt
Your expected result is actually an operation of symmetric difference in terms of sets, but since collections.Counter doesn't support such an operation, you can emulate it with:
xy = Counter(X) + Counter(Y)
z = Counter(Z)
res = z - xy | xy - z
res becomes:
Counter({'f': 10, 'd': 7, 'e': 6, 'c': 5, 'a': 2})
But if you do want keys with value of 0, which Counter would hide from its output, you would have to iterate through a union of the keys of the 3 dicts:
{k: res.get(k, 0) for k in {*X, *Y, *Z}}
This returns:
{'a': 2, 'd': 7, 'e': 6, 'b': 0, 'f': 10, 'c': 5}

How to multiple values of keys with different numbers in dictionary?

Im trying to multiple some values from dictionary
example
price_list = {'a': 3, 'b': 2, 'c': 5, 'd': 10}
when i type
total=sum(price_list.values())
print("Total sum is ",total)
it result 20
But now i want to multiple a with 3, b with 5, c with 2 and d with 3 and my desired output to be 59. What is easiest way to do that?
Assuming your numbers are stored in the list, iterate through the values, and multiply with your required number like so
price_dict = {'a': 3, 'b': 2, 'c': 5, 'd': 10}
numbers_dict = {'a': 3, 'b': 5, 'c': 2, 'd': 3}
result = 0
for key, value in price_dict.items():
result += numbers_dict[key] * value
print(result)
#59
You can just perform operations on the dictionary item like you would any other variable:
# multiply 'a' by 3
price_list['a'] *= 3
Try this:
price_list = {'a': 3, 'b': 2, 'c': 5, 'd': 10}
numbers = [3,5,2,3]
for k,n in list(zip(price_list, numbers)):
price_list[k] *= n
then the price list will change, you can use sum as you did to calculate the result.

Categories