I need help with a function that outputs a dictionary that contains the composition between R1 and R2 it's output represents R2 ◦ R1
as of now, I have
def composition(R1,R2):
d = {i:R2[R1[i]] for i in R1}
print(d)
this function works inputting
R1 = {1:'a',2:'b',3:'c'}
R2 = {'a':'A','b':'B','c':'C'}
output: {1: 'A', 2: 'B', 3: 'C'}
what I need to work is
R1 = {1 : [2, 3], 2 : [3], 3 : [4], 4 : [1, 3]}
R2 = {1 : [3], 2 : [1, 4], 3 : [2], 4 : [1, 2]}
output should be: R2 ◦ R1 = {1 : [1, 2, 4], 2 : [2], 3 : [1, 2], 4 : [2, 3]}
what I get is unhashable type list
Any help would be great, Thank You.
CodePudding user response:
Since both the values of R1 and R2 are lists, you need nested comprehensions to get all the mapped elements in a flattened result for each key:
R1 = {1 : [2, 3], 2 : [3], 3 : [4], 4 : [1, 3]}
R2 = {1 : [3], 2 : [1, 4], 3 : [2], 4 : [1, 2]}
output = {k1:[n2 for n1 in v1 for n2 in R2[n1]] for k1,v1 in R1.items()}
print(output)
{1: [1, 4, 2], 2: [2], 3: [1, 2], 4: [3, 2]}
CodePudding user response:
Here is a generic solution working in both cases.
In summary, check if the value is a non-string iterable and compose all elements, else just compose the value.
from collections.abc import Iterable
from itertools import chain
def composition(R1, R2):
return {k1: list(chain(*[R2[e] for e in v1]))
if isinstance(v1, Iterable)
and not isinstance(v1, str)
else v1
for k1,v1 in R1.items()}
Example 1:
>>> R1 = {1:'a',2:'b',3:'c'}
>>> R2 = {'a':'A','b':'B','c':'C'}
>>> composition(R1, R2)
{1: 'a', 2: 'b', 3: 'c'}
Example 2:
>>> R1 = {1 : [2, 3], 2 : [3], 3 : [4], 4 : [1, 3]}
>>> R2 = {1 : [3], 2 : [1, 4], 3 : [2], 4 : [1, 2]}
>>> composition(R1, R2)
{1: [1, 4, 2], 2: [2], 3: [1, 2], 4: [3, 2]}
CodePudding user response:
It's a little convoluted to write in Python using list comprehension alone (maybe readability can be a bit improved by using functools.reduce
to collapse the sublists), but it should be something like this:
def composition(R1, R2):
d = {
i: [
val
for sublist in [R2[j] for j in R1[i]]
for val in sublist
]
for i in R1
}
print(d)