# 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.

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.

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


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.

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