Check for multiple kv in a dictonary with a twist - python-3.x

I have a search list of dicts that I need to check if exist in another source dict.
source_dict = { 'a':'1', 'blue':'yes', 'c':'3' }
search_list = [ {'a':'1', 'b':'2'}, {'blue': 'yes'} ]
The items in the list all need to be checked however, we need a AND for all items in the same dict. OR between dicts in the list.
How would I start to tackle this problem?

You can use any and all:
>>> # the `OR` (`any`) of the `AND`s (`all`s) for each dict
>>> any(all(k in source_dict and source_dict[k] == v for k, v in d.items()) for d in search_list)
True
>>> # the `AND`s (`all`s) for each dict
>>> [all(k in source_dict and source_dict[k] == v for k, v in d.items()) for d in search_list]
[False, True]

any(map(lambda x: all(map(lambda k: source_dict[k] == x[k] if k in source_dict else False, x.keys())), search_list))

Related

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'}

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.

return dictionary of file names as keys and word lists with words unique to file as values

I am trying to write a function to extract only words unique to each key and list them in a dictionary output like {"key1": "unique words", "key2": "unique words", ... }. I start out with a dictionary. To test with I created a simple dictionary:
d = {1:["one", "two", "three"], 2:["two", "four",
"five"], 3:["one","four", "six"]}
My output should be:
{1:"three",
2:"five",
3:"six"}
I am thinking maybe split in to separate lists
def return_unique(dct):
Klist = list(dct.keys())
Vlist = list(dct.values())
aList = []
for i in range(len(Vlist)):
for j in Vlist[i]:
if
What I'm stuck on is how do I tell Python to do this: if Vlist[i][j] is not in the rest of Vlist then aList.append(Vlist[i][j]).
Thank you.
You can try something like this:
def return_unique(data):
all_values = []
for i in data.values(): # Get all values
all_values = all_values + i
unique_values = set([x for x in all_values if all_values.count(x) == 1]) # Values which are not duplicated
for key, value in data.items(): # For Python 3.x ( For Python 2.x -> data.iteritems())
for item in value: # Comparing values of two lists
for item1 in unique_values:
if item == item1:
data[key] = item
return data
d = {1:["one", "two", "three"], 2:["two", "four", "five"], 3:["one","four", "six"]}
print (return_unique(d))
result >> {1: 'three', 2: 'five', 3: 'six'}
Since a key may have more than one unique word associated with it, it makes sense for the values in the new dictionary to be a container type object to hold the unique words.
The set difference operator returns the difference between 2 sets:
>>> a = set([1, 2, 3])
>>> b = set([2, 4, 6])
>>> a - b
{1, 3}
We can use this to get the values unique to each key. Packaging these into a simple function yields:
def unique_words_dict(data):
res = {}
values = []
for k in data:
for g in data:
if g != k:
values += data[g]
res[k] = set(data[k]) - set(values)
values = []
return res
>>> d = {1:["one", "two", "three"],
2:["two", "four", "five"],
3:["one","four", "six"]}
>>> unique_words_dict(d)
{1: {'three'}, 2: {'five'}, 3: {'six'}}
If you only had to do this once, then you might be interested in the less efficeint but more consice dictionary comprehension:
>>> from functools import reduce
>>> {k: set(d[k]) - set(reduce(lambda a, b: a+b, [d[g] for g in d if g!=k], [])) for k in d}
{1: {'three'}, 2: {'five'}, 3: {'six'}}

How to remove a character from the values of a dictionary?

dict_data = {'c': ['d\n', 'e\n'], 'm':['r\n','z\n','o']}
a dictionary dict_data remove '\n' in the values
(order is not important.):
should return: {'c': ['d', 'e'], 'm':['r','z','o']}
This is what I tried:
def dicts(dict_data):
for k, v in dict_data.items():
for i in v:
f = i.strip('\n')
return f
How can i get this without doing anything to complicated?
You were on the right approach but you've probably assumed that altering i with i.strip('\n') in for i in v might make the change appear in dict_data. This isn't the case. What you're doing is altering i and then discarding the result.
A correct approach would be to build a list of the stripped elements and re-assign to the corresponding dictionary key:
def strip_dicts(dict_data):
for k, v in dict_data.items():
f = []
for i in v:
f.append(i.strip('\n'))
dict_data[k] = f
of course, remember, this alters the argument dictionary in-place.
You can create a different function that returns a new dictionary by using a comprehension:
def strip_dicts(d):
return {k: [i.strip() for i in v] for k,v in d.items()}

Resources