keep certain values in a dictionary values based on list - python-3.x

I have a dictionary d
d = {'1': ['Fisherman', 'fam', '125', '53901', 'funny'],
'2': ['Joi', '521', 'funny','fun', '1245']}
and a list l
l = ['521', 'Fisherman', 'fun','A2ML1', 'A3GALT2','funny']
I want to keep values in d that are not in l. I want my output to be
d_list = {'1': ['fam','125', '53901'],'2': ['Joi', '1245']}
To do so, I tried this
d_list = []
for k, v in d.items():
if v not in l:
d_list.append(v)
But this doesn't give me what I want. What can I do to my code (or new code) to get my desired d_list?

v is a list not a str
try this code:
d1 = {}
for k, v in d.items():
d1[k] = [i for i in v if i not in l]
d1
output:
{'1': ['fam', '125', '53901'], '2': ['Joi', '1245']}

you can doe it like this also
{key:set(values) - set(l) for key, values in d.items()}
or if you want values to be list instead of set
{key:list(set(values) - set(l)) for key, values in d.items()}

Related

How to split list of values of a dict according to list of values from another dict?

I have the 2 below dictionaries:
d1 = {'1':['a','b','c'],'2':['a','b','c','e'],'4':['a','f','c']}
d2 = {'1':['nm','nm','st'],'2':['nm','nm','nm','nm'],'4':['st','nm','da']}
Each element of the values with same index, same key are 'together'. For example, for key 1, 'a' in d1 is connected to 'nm' in d2, 'b' is connected to 'nm' and 'c' is connected to 'st'.
I'm trying to split the list of values from d1 according to the list of values from d2. In my final dict, I would have:
{key:[[all values from d1 where d2='nm'], [all values from d1 where d2='da'], [all values from d1 where d2='st']]}
Here the result I want is for the d1, d2 example above, empty lists would be out ideally:
res = {'1':[['a','b'],['c']],'2':[['a','b','c','e']],'4':[['f'],['c'],['a']]}
Any idea how I can reach there? I have no clue how to reach there, I am aware of groupby() but I was not able to use it properly - not even sure that it would work here.
Using itertools.groupby
Ex:
from itertools import groupby
d1 = {'1':['a','b','c'],'2':['a','b','c','e'],'4':['a','f','c']}
d2 = {'1':['nm','nm','st'],'2':['nm','nm','nm','nm'],'4':['st','nm','da']}
result = {}
for k, v in d1.items():
for m, n in groupby(zip(v, d2[k]), lambda x: x[1]):
result.setdefault(k, []).append([s for s, _ in n])
print(result)
Or using just dict.setdefault
result = {}
for k, v in d1.items():
temp = {}
for m, n in zip(v, d2[k]):
temp.setdefault(n, []).append(m)
result[k] = list(temp.values())
print(result)
Output:
{'1': [['a', 'b'], ['c']],
'2': [['a', 'b', 'c', 'e']],
'4': [['a'], ['f'], ['c']]}
Similar solution to above just slightly different. Also uses group by and zip to get your output.
from itertools import groupby
d1 = {'1':['a','b','c'],'2':['a','b','c','e'],'4':['a','f','c']}
d2 = {'1':['nm','nm','st'],'2':['nm','nm','nm','nm'],'4':['st','nm','da']}
d3 = {}
for key in d1:
d3[key] = [[e[0] for e in group] for _, group in groupby(zip(d1[key], d2[key]), key=lambda x: x[1])]
print(d3)
Output:
{'1': [['a', 'b'], ['c']], '2': [['a', 'b', 'c', 'e']], '4': [['a'], ['f'], ['c']]}

swap the keys and values in a dictionary by storing the user input in dic

First the input should be dic length consider 3. then the input to a dic is keys and values separated by spaces i,e
"A 1
B 2
C 1"
now dic={A:1, B:2, C:1}
At first the keys and values and should be swapped, and if there are same keys and there values should be merged in a list and assigned to the same key as shown below.(these program should work for any length of dictionary)
the output should be dicout={1:['A','C'], 2:B}.
Thank you.
Define:
from collections import defaultdict
def make_dict(s):
d = defaultdict(list)
xs = s.split(" ")
for k, v in zip(xs[1::2], xs[::2]):
d[k].append(v)
for k, v in d.items():
if len(v) == 1:
d[k] = v[0]
return dict(d)
Example usage:
>>> make_dict("A 1 B 2 C 1")
{'1': ['A', 'C'], '2': 'B'}

keeping certain values from list and dict

I have a dict d
d = {'A1': ['Mike', 'Mouse'],
'A2': ['Don', 'Duck'],
'A3': ['Bart','Simp']}
and a list l
l = ['Sar', 'Mike', 'Duck', 'Hox12', 'Bart', '10r']
My goal is to create a new list new_l that does not have the items in l e.g. Mike that are also in d e.g. 'A1': ['Mike', 'Mouse'].
I would like my new_l to be
new_l = ['Sar', 'Hox12', '10r]
I have tried
new_l = []
for k, v in d.items():
if v not in l:
new_l.append(v)
and
new_l = []
for names in l:
if names not in v in d.items():
new_l.append(names)
But they both do not give me my desired output.
How do I change my code to get my desired new_l?
use extend functionality to prepare a list using dict values.
new_l = []
d = {'A1': ['Mike', 'Mouse'],
'A2': ['Don', 'Duck'],
'A3': ['Bart','Simp']}
l = ['Sar', 'Mike', 'Duck', 'Hox12', 'Bart', '10r']
to_cmp_l = []
for k,v in d.items():
to_cmp_l.extend(v)
for item in l:
if item not in to_cmp_l:
new_l.append(item)
print(new_l)
s = set()
for v in d.values():
s |= set(v)
new_l = [e in l if e not in s]
convert each value to set and build a set of all values in the dictionary. Build the new list by checking for membership in the set.
You could use a list instead of a set, though a set has certain advantages, namely that elements are unique and the membership test is a constant time operation.
|= is shorthand for adding elements to an existing set. Docs
You can also try this one-liner:
new_l = reduce(list.__add__, [list(set(items) - set(l)) for items in d.values()])

Accessing nested list and dictionaries

A = {'a':1, 'b':2, 'c':3}
B = {1:['a', 'b', 'c']}
The answer I need is to get the key from B and for each element in its value, which is a list, replace it with its value from A, like the following:
D = {1:[1,2,3]}
A[B[1][0]] - will give you the value of 'a'
A[B[1][1]] - will give you the value of 'b' and so on...
Here is mt solution:
A = {'a':1, 'b':2, 'c':3}
B = {1:['a', 'b', 'c']}
D = {}
for key, value in B.items():
D[key] = []
for oneValue in value:
D[key].append(A[oneValue]);
print D;
This will work for you:
A = {'a':1, 'b':2, 'c':3}
B = {1:['a', 'b', 'c']}
for key, value in B.items(): # loop in dict B
# loop in every list in B, use items as key to get values from A
# default to None if key doesn't exists in A and put it in a new temp list
l = [A.get(x, None) for x in value]
# Simplified version of line above
# l = []
# for x in value:
# l.append(A.get(x, None))
D[key] = l # use key of B as key and your new list value and add it to D
Or if you like to be too cleaver then:
# Doing same things as the last example but in one line
# which is hard to read and understand. Don't do this
D = {k: [A.get(x, None) for x in v] for k, v in B.items()}
In place editing B:
for key in B.keys():
for i in range(len(B[key])):
B[key][i] = A[B[key][i]]
Create a new D for returning
D = B.copy()
for key in D.keys():
for i in range(len(D[key])):
D[key][i] = A[D[key][i]]
I tested the code and it worked.

How to conditionally delete Keys from multiple Python dictionaries. The condition is (Value <= time.time()- 15)

In Python 3.6, how can efficiently remove certain Keys from the three dictionaries based on whether or not their Value is 15 seconds old or older?
The three dictionaries store Integer Ids as Keys (1111, etc) and Epoch Integers as Values(915824792, etc)
import time
dict1 = {1111: 915824792, 2222:1053632792, 1234:2211219992, ...}
dict2 = {1114: 1291837592, 9999:1580067992, 2317:2242496792, ...}
dict3 = {1777: 1229543192, 8888:1895687192, 2319:3725639192, ...}
[v for k,v in dict1.items() if v <= (time.time()-15)] # This is not complete, idk how to conditionally delete Keys from a dictionary, and idk if my syntax is correct
[v for k,v in dict2.items() if v <= (time.time()-15)] # This is not complete, idk how to conditionally delete Keys from a dictionary, and idk if my syntax is correct
[v for k,v in dict3.items() if v <= (time.time()-15)] # This is not complete, idk how to conditionally delete Keys from a dictionary, and idk if my syntax is correct
# https://stackoverflow.com/a/4181492/6200445
You could try to build a new dict with comprehension:
dict1 = {1111: 915824792, 2222:1053632792, 1234:2211219992}
dict2 = {1114: 1291837592, 9999:1580067992, 2317:2242496792}
dict3 = {1777: 1229543192, 8888:1895687192, 2319:3725639192}
import time
now = time.time()
filter_v = now - 15
# 1554498239.9005954
new_dict1 = {
k: v
for k, v in dict1.items()
if v <= filter_v}
# {1111: 915824792, 2222: 1053632792}
Repeat for each of the dicts, if you want them separate
new_dict2 = {
k: v
for k, v in dict2.items()
if v <= filter_v}
new_dict3 = {
k: v
for k, v in dict3.items()
if v <= filter_v}
Is that what you need?
If you have many dicts that you want to keep separate but filter out a few elements in each, you could use a list to hold all those dicts:
import time
now = time.time()
filter_v = now - 15
dict_list = [
{1111: 915824792, 2222:1053632792, 1234:2211219992},
{1114: 1291837592, 9999:1580067992, 2317:2242496792},
{1777: 1229543192, 8888:1895687192, 2319:3725639192},
]
# create new list with new dicts
new_dict_list = [
{k: v
for k, v in d.items()
if v <= filter_v}
for d in dict_list]
You can use a dictionary comprehension to do what you want. Your current code is about 90% of the way there:
threshold = time.time()-15 # helps performance to compute this only once
dict1 = {k: v for k, v in dict1.items() if v <= threshold}
dict2 = {k: v for k, v in dict2.items() if v <= threshold}
dict3 = {k: v for k, v in dict3.items() if v <= threshold}
While that works, it's not especially efficient, since it needs to iterate over all the values in all the dictionaries. If a lot of the values are not going to be expired, you may want to find a better way. One idea is to put value, key, dictionary tuples into a heap, and pop them off until the smallest value is greater than the threshold. The heapq module lets you build heaps easily:
import heapq
from collections import counter
dict1 = {1111: 915824792, 2222:1053632792, 1234:2211219992}
dict2 = {1114: 1291837592, 9999:1580067992, 2317:2242496792}
dict3 = {1777: 1229543192, 8888:1895687192, 2319:3725639192}
heap = []
tie_breaker = counter()
for k, v in dict1.items():
heapq.heappush(heap, (v, k, tie_breaker(), dict1))
for k, v in dict2.items():
heapq.heappush(heap, (v, k, tie_breaker(), dict2))
for k, v in dict3.items():
heapq.heappush(heap, (v, k, tie_breaker(), dict3))
threshold = time.time()-15
while heap[0][0] <= threshold:
v, k, tb, dct = heapq.heappop(heap)
del dct[k]
Note that if you're repeatedly doing this expiration, you don't need to repeat the for loops putting all the items into the heap, just add each new element to the heap at the same time you add to one of the dictionaries.

Resources