keeping certain values from list and dict - python-3.x

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()])

Related

Check for multiple kv in a dictonary with a twist

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))

keep certain values in a dictionary values based on list

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()}

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

Resources