Find intersection of dictionary values list - python

I have two dictionaries with the same keys, while the values are variant:
a = {1: [1, 2, 3, 4, 5], 2: [6, 7, 8], 3: [1, 3, 5, 7, 9]}
b = {1: [2, 3, 4, 7], 2: [6, 7], 3: [1, 3, 15, 10]}
I'm trying to get the intersection under the same keys. I want this output:
{1: [2, 3, 4], 2: [6, 7], 3: [1, 3]}
I tried with this command:
dict(zip(a.keys() and b.keys(), a.values() and b.values()))
output: {1: [2, 3, 4, 7], 2: [6, 7], 3: [1, 3, 15, 10]}
However, the output is the following, which is wrong:
{1: [2, 3, 4, 7], 2: [6, 7], 3: [1, 3, 15, 10]}

I think it is pretty clear. If not, please ask for clarification.
Assuming,
I have two dictionaries with the same keys
a = {1: [1, 2, 3, 4, 5], 2: [6, 7, 8], 3: [1, 3, 5, 7, 9]}
b = {1: [2, 3, 4, 7], 2: [6, 7], 3: [1, 3, 15, 10]}
c = {}
for key, val in a.items():
c[key] = []
for i in val:
if i in b[key]:
c[key].append(i)
print(c)
The output is:
{1: [2, 3, 4], 2: [6, 7], 3: [1, 3]}

If you know the dictionaries have the same keys, you could do
c = {}
for key, list_a, list_b in zip(a.keys(), a.values(), b.values()):
c[key] = [value for value in list_a if value in list_b]
Or:
c = {}
for key, list_a, list_b in zip(a.keys(), a.values(), b.values()):
c[key] = list(set(list_a).intersection(list_b))
If you're not sure they have the same keys, just add a condition, like
c = {}
for key_a, list_a, key_b, list_b in zip(a.keys(), a.values(), b.keys(), b.values()):
if key_a == key_b:
c[key_a] = [value for value in list_a if value in list_b]

c= {key:list(set(a[key]) & set(b[key])) for key in a}
Explanation: using dictionary comprehension, I went through each key of 'a', & create an intersection of list of values corresponding to that key in both the dictionaries 'a' & 'b'

Related

how to classify a list of lists by elements length?

I have a list of lists, looks like this :
List=[[1,3],[3,4,7,9],[4,7],[2,4,5,3],[5,7,4]]
I want to classify the list elements according to their length, so the result looks like this:
2ElelmentSublist=[[1,3],[4,7]]
4ElementSublist=[[3,4,7,9],[2,4,5,3]]
....
And so on.
I read a post about itertools.groupby(),
But I couldn’t figure out how to apply it in my case.
Any pythonic way to do so?
Note: no need to have the result in separate variables,I need a way to know how many types of lengths I have, and a way to reach every group separately.
Thank you in advance.
You can't make lists with dynamic names to be decided at run-time (like your 2ElementSublist or so.)
But you can design a dictionary with keys as length, and values as lists of lists.
Try this:
result = {}
for L in List:
result.setdefault(len(L), list()).append(L)
print(result)
and you will see
{2: [[1, 3], [4, 7]], 4: [[3, 4, 7, 9], [2, 4, 5, 3]], 3: [[5, 7, 4]]}
.setdefault(k, d) either gives you access to the dictionary value of key k, or initialize with a default value d. And you append each list.
Might not be the most pythonic, but you can call values similar to how you wanted.
x = [[1,3],[3,4,7,9],[4,7],[2,4,5,3],[5,7,4]]
dic = {f"{len(i)}_elelment": [] for i in x}
for i in x:
dic[f"{len(i)}_elelment"].append(i)
# {'2_elelment': [[1, 3], [4, 7]],
# '4_elelment': [[3, 4, 7, 9], [2, 4, 5, 3]],
# '3_elelment': [[5, 7, 4]]}
Since you have mentioned you need the list grouped by len and need them in seperate variable I think you will be needing a dict as your final output.
from itertools import groupby, chain
from collections import defaultdict
List=[[1,3],[3,4,7,9],[4,7],[2,4,5,3],[5,7,4]]
res = defaultdict(list)
for _, v in groupby(sorted(List, key=len)):
l = list(chain(*v))
res[len(l)].append(l)
# Output : defaultdict(list,
{2: [[1, 3], [4, 7]],
3: [[5, 7, 4]],
4: [[3, 4, 7, 9], [2, 4, 5, 3]]})
You can try this:
List = [[1,3],[3,4,7,9],[4,7],[2,4,5,3],[5,7,4]]
sizes = set([(len(element)) for element in List])
result = {}
for element in List:
if len(element) not in result.keys():
result[len(element)] = []
result[len(element)].append(element)
print(result)
And result is:
{2: [[1, 3], [4, 7]], 4: [[3, 4, 7, 9], [2, 4, 5, 3]], 3: [[5, 7, 4]]}
Use groupby by len:
Ex:
from itertools import groupby
lst = [[1,3],[3,4,7,9],[4,7],[2,4,5,3],[5,7,4]]
print( [list(v) for k, v in groupby(sorted(lst, key=len), key=len)] )
#or
print( {k: list(v) for k, v in groupby(sorted(lst, key=len), key=len)} )
Output:
[[[1, 3], [4, 7]], [[5, 7, 4]], [[3, 4, 7, 9], [2, 4, 5, 3]]]
{2: [[1, 3], [4, 7]], 3: [[5, 7, 4]], 4: [[3, 4, 7, 9], [2, 4, 5, 3]]}

python updating global dict inside recursive function

I am trying to find all permutations of elements in a list and add it to a global dictionary
Code:
outp={}
k=0
def func(i,arr):
global outp
global k
arr=arr.copy()
for j in range(i,len(list)):
arr[i],arr[j] = arr[j],arr[i]
if i!=j or i==0:
k=k+1
print("\n\n",arr,k)
outp[k]=arr
print("\n",outp)
func(i+1,arr)
list = [1,2,3,8]
func(0,list)
Output below:
Till 4th element it updated correctly. During 5th element, it updated both 5th and 3rd element in the dictionary. I don't know why it is happening. Kindly help
[1, 2, 3, 8] 1
{1: [1, 2, 3, 8]}
[1, 2, 8, 3] 2
{1: [1, 2, 3, 8], 2: [1, 2, 8, 3]}
[1, 3, 2, 8] 3
{1: [1, 2, 3, 8], 2: [1, 2, 8, 3], 3: [1, 3, 2, 8]}
[1, 3, 8, 2] 4
{1: [1, 2, 3, 8], 2: [1, 2, 8, 3], 3: [1, 3, 2, 8], 4: [1, 3, 8, 2]}
[1, 8, 2, 3] 5
{1: [1, 2, 3, 8], 2: [1, 2, 8, 3], 3: [1, 8, 2, 3], 4: [1, 3, 8, 2], 5: [1, 8, 2, 3]}
You need to place a copy of the array in the dictionary:
outp[k] = arr.copy()
This would be a better way to copy list to a new list.
arr=arr[:] .
https://repl.it/repls/BronzeYellowConversion

Combining Lists Until Desired List Is Made

If I have the following Dictionary of Lists:
{1: [2], 2: [1, 3, 5], 3: [2, 4], 4: [3, 7], 5: [2, 6], 6: [5], 7: [8, 4], 8: [7]}
I want to know the keys I'll need a full set of:
[1,2,3,4,5,6,7,8]
Using the smallest number of keys. For this particular problem for example it would be:
keys needed: [2,5,7]
While the order doesn't matter I want to use as few keys as possible. Is there an easy way to do this and to test if my answer is the shortest possible answer?
Here comes the bruteforce solution, using itertools.combinations:
from itertools import combinations
data = {1: [2], 2: [1, 3, 5], 3: [2, 4], 4: [3, 7], 5: [2, 6], 6: [5], 7: [8, 4], 8: [7]}
desired_set = set([1, 2, 3, 4, 5, 6, 7, 8])
n = len(data)
all_values = set(x for values in data.values() for x in values)
if all_values.issuperset(desired_set):
print("There must be a solution...")
n = len(data)
for i in range(0, n + 1):
for combination in combinations(data, i):
values = set(x for key in combination for x in data[key])
if values.issuperset(desired_set):
print("FOUND!")
print("Keys needed : %r" % list(combination))
print("Values : %r" % list(values))
quit()
else:
print "Not possible. Not even trying"
It outputs:
FOUND!
Keys needed : [2, 4, 5, 7]
Values : [1, 2, 3, 4, 5, 6, 7, 8]
Worst case complexity is O(2**n) though, so don't use it on big datasets!
Note that you need 4 as key to get 7 as value.
If you mean values instead of keys, here you go.
d = {1: [2], 2: [1, 3, 5], 3: [2, 4], 4: [3, 7], 5: [2, 6], 6: [5], 7: [8, 4], 8: [7]}
#get the values from all elements and use a set to remove duplicate and then use sum to flatten the list.
list(set(sum(d.values(),[])))
Out[806]: [1, 2, 3, 4, 5, 6, 7, 8]
If you just want the keys in order, you can call sorted() directly on the dictionary.
some_dict = {1: [2], 2: [1, 3, 5], 3: [2, 4], 4: [3, 7], 5: [2, 6], 6: [5], 7: [8, 4], 8: [7]}
keys = sorted(some_dict)
print(keys)
[1, 2, 3, 4, 5, 6, 7, 8]
If, on the other hand, you want all the unique VALUES in the dictionary in sorted order, you should sort a set.
values = sorted({x for key in some_dict for x in some_dict[key]})
print(values)
[1, 2, 3, 4, 5, 6, 7, 8]
I don't know why you would want to use the shortest possible number of keys, but you can do so as follows.
wanted = set(range(1, 9))
seen = set()
for key in some_dict:
seen |= set(some_dict[key])
if seen == wanted:
break

Can I remove a single value from a dictionary?

I have a dictionary and I want to remove a single value from a key:values combination.
For example, when having the following dictionary:
d = {1: [2, 3, 4, 7], 2: [1, 3, 4]}
I'd like to remove the key:value 1:2, so that the dictionary becomes:
{1: [3, 4, 7], 2: [1, 3, 4]}
Is this doable?
You have a dict that holds lists.
The lists can be manipulated in the usual manner
d = {1: [2, 3, 4, 7], 2: [1, 3, 4]}
d[1].remove(2)
print(d)
# {1: [3, 4, 7], 2: [1, 3, 4]}
Well, first find a reference to list, then remove an item with value 2 from list, so:
d[1].remove(2)
d = {1: [2, 3, 4, 7], 2: [1, 3, 4]}
d[1].remove(2)
print d

substracting elements of a dictionary

I have a dictionary made up of lists:
>>> triplets.get(k)
[[1, 3, 15], [1, 3, 13], [1, 3, 11], [1, 3, 9], [1, 3, 8], [1, 3, 5], [1, 4, 15]
and also dictionaries:
>>> cset1.get(k)
[set([5])]
>>> cset2.get(k)
[[1, 8], [1, 9], [1, 11]]
I want to delete elements of triplets which contain the element of cset1 or both elements of cset2, i.e. I want to delete [1,3,5] which contains [5] and also [1, 3, 8], [1, 3, 9], [1, 3, 11] which contain both elements of cset2.
I have the following piece of code (which doesn't do anything at all):
CDln = len(triplets.get(k))
for ii in range(CDln):
if cset1.get(k) in triplets.get(k)[ii] or cset2.get(k) in triplets.get(k)[ii]:
print "delete element of triplets in location:", ii
I cannot figure out how to delete those elements from dictionary triplets (I use the print statement as a dummy of what I want).
I am not quite sure if I got you right, but take a look and comment please:
k = 42 #whatever
triplets = {k: [[1, 3, 15], [1, 3, 13], [1, 3, 11], [1, 3, 9], [1, 3, 8], [1, 3, 5], [1, 4, 15]]}
cset1 = {k: [set([5])]}
cset2 = {k: [{1, 8}, {1, 9}, {1, 11}]} #changed this to sets
triplets[k] = [x for x in triplets[k] if
all (y - set(x) for y in cset1[k]) and
all (y - set(x) for y in cset2[k])
]
print(triplets[k])
I'm not sure what ii is, but I think this is what you want.
b = cset1[k]
c = cset2[k]
triplets[k] = filter(
lambda lst:
any(lambda x: x in b, lst) or
any(lambda c1: all(lambda x: x in c1), c),
triplets[k]
]
But:
I wonder why you have a cset1 and cset2. It seems as though, you should just have cset2, whose value is
[[5], [1, 8], [1, 9], [1, 11]]

Categories

Resources