# Applying a bivariate function to a list of couples

I have this function :

def F(v,a):
if v > a :
return 4*a - 3*(v-a)
else :
return v - 2*(a-v)^2


I want to applied it to L2 define by

L0=list(range(4))
L1=list(range(4))
L2=flatten([[(v,a) for v in L0] for a in L1],max_level=1)


The only way I found to do this is the following

Vv=[(x,F(x[0],x[1])) for x in L2]
Vv


I wonder if there is a more efficient, elegant way to do this like with apply_map().

edit retag close merge delete

Sort by » oldest newest most voted

Two possibilities (among others I suppose...) :

sage: [F(u[0], u[1]) for u in L2]
[0, -3, -6, -9, -2, 1, 1, -2, -8, -1, 2, 5, -18, -7, 0, 3]


You can pass a list (or other iterable) of arguments via indirection :

sage: [F(*u) for u in L2]
[0, -3, -6, -9, -2, 1, 1, -2, -8, -1, 2, 5, -18, -7, 0, 3]


or equivalently (see map?) :

sage: list(map(lambda u:F(*u), L2))
[0, -3, -6, -9, -2, 1, 1, -2, -8, -1, 2, 5, -18, -7, 0, 3]


Building L2 isn't necessary :

sage: [F(*u) for u in Set(L0).cartesian_product(Set(L1))]
[0, -2, -8, -18, -3, 1, -1, -7, -6, 1, 2, 0, -9, -2, 5, 3]


I suppose that the itertools standard Pythonlibrary offers other possibilities...

Personally, I'd dispense with L2 and would simply do :

sage: table([[F(u, v) for v in L1] for u in L0], header_column=["F"]+L0, header_row=L1)
F | 0    1    2    3
+---+----+----+----+-----+
0 | 0    -2   -8   -18
1 | -3   1    -1   -7
2 | -6   1    2    0
3 | -9   -2   5    3


Learn Python !

HTH,

more

I learn step by step. In all cases thank you.

( 2023-03-04 15:15:52 +0200 )edit

If all 16 values are expected, then you can do also:

def F(x):
v=x[0];a=x[1]
if v > a :
return 4*a - 3*(v-a)
else :
return v - 2*(a-v)^2

L0=range(4)
L3=cartesian_product([L0,L0]);
list(zip(L3,map(F,L3)))

more