# Construct vectors or lists with 'for', 'if' and 'else'

I'm trying to generate some vectors (or lists) recursively, but I'm getting some trouble in the procedure:

def p(*t):
return SR.var(('p' + '_{}' * len(t)).format(*t))
l= Permutations(3)
for i in (1..3):
for u in (1..3):
p(i,u) = [1 for m in (0..5) if l[m][i-1]==u else 0]


This code below returns 'invalid syntax'. How can I generate the list p's with entrance equal to one if l[m][i-1]=u and zero in the rest? Can I generate a matrix with the same idea?

edit retag close merge delete

I think you cannot use else when if comes after for in the list comprehension. Try [ int( l[m][i-1]==u ) for m in (0..5) ] instead.

( 2021-02-10 02:07:59 +0100 )edit

Sort by » oldest newest most voted

Maybe the following does what you want?

sage: p = dict()
sage: P = Permutations(3)
sage: for i in (1 .. 3):
....:     for u in (1 .. 3):
....:         p[i, u] = [1 if P[m][i-1] == u else 0 for m in (0 .. 5)]


Usage:

sage: p
{(1, 1): [1, 1, 0, 0, 0, 0],
(1, 2): [0, 0, 1, 1, 0, 0],
(1, 3): [0, 0, 0, 0, 1, 1],
(2, 1): [0, 0, 1, 0, 1, 0],
(2, 2): [1, 0, 0, 0, 0, 1],
(2, 3): [0, 1, 0, 1, 0, 0],
(3, 1): [0, 0, 0, 1, 0, 1],
(3, 2): [0, 1, 0, 0, 1, 0],
(3, 3): [1, 0, 1, 0, 0, 0]}

sage: p[2, 3]
[0, 1, 0, 1, 0, 0]


Note that you could replace

p[i, u] = [1 if P[m][i-1] == u else 0 for m in (0 .. 5)]


by

p[i, u] = [Integer(P[m][i-1] == u) for m in (0 .. 5)]

more

Your error was the consequence of a weird grammatical trick of Python. If ifcomes alone the syntax is :

stuff... if ... for...

but in the presence of an else the order is inversed

stuff... for ... if... else...

It helps to remember this.

( 2021-02-10 08:33:28 +0100 )edit

Nope (at least for Python 3-based Sage) :

sage: [u for u in (1..10) if u.is_prime()]
[2, 3, 5, 7]
sage: [u if u.is_prime() for u in (1..10)]
File "<ipython-input-16-1654bfae669e>", line 1
[u if u.is_prime() for u in (ellipsis_iter(Integer(1),Ellipsis,Integer(10)))]
^
SyntaxError: invalid syntax

( 2021-02-10 09:18:26 +0100 )edit

Thank you for the help.

( 2021-02-10 13:58:45 +0100 )edit

What comes before for is considered a function, and it cannot contain if without else since it'd would not be well defined. So, [u if u.is_prime() for u in (1..10)] is invalid construction, but [u if u.is_prime() else 0 for u in (1..10)] is fine. Please notice that this is different from the case when if comes afterfor, when it's used for filtering of function arguments and cannot be followed by else.

( 2021-02-10 15:49:05 +0100 )edit

Is there an easy way to say that some element is different from another?

( 2021-02-11 22:56:39 +0100 )edit