440,550 Members | 1,161 Online
Need help? Post your question and get tips & solutions from a community of 440,550 IT Pros & Developers. It's quick & easy.

# Modifying every alternate element of a sequence

 P: n/a I have a list of numbers and I want to build another list with every second element multiplied by -1. input = [1,2,3,4,5,6] wanted = [1,-2,3,-4,5,-6] I can implement it like this: input = range(3,12) wanted = [] for (i,v) in enumerate(input): if i%2 == 0: wanted.append(v) else: wanted.append(-v) But is there any other better way to do this. -- Suresh Nov 28 '06 #1
9 Replies

 P: n/a jm*******@no.spam.gmail.com wrote: I have a list of numbers and I want to build another list with every second element multiplied by -1. input = [1,2,3,4,5,6] wanted = [1,-2,3,-4,5,-6] I can implement it like this: input = range(3,12) wanted = [] for (i,v) in enumerate(input): if i%2 == 0: wanted.append(v) else: wanted.append(-v) But is there any other better way to do this. -- Suresh I would tend to do this as a list comprehension. In python 2.5 you can do this: wanted = [(v if i % 2 == 0 else -v) for (i,v) in enumerate(input)] (a if b else c) is new to Python 2.5. You don't always need the brackets, but I think it makes things clearer. See (http://docs.python.org/whatsnew/pep-308.html) for more details on this feature. With earlier versions, you could do wanted = [v - 2*(i % 2) for (i,v) in enumerate(input)] That looks less clear to me than your version, though. John Hicken Nov 28 '06 #2

 P: n/a I have a list of numbers and I want to build another list with every second element multiplied by -1. input = [1,2,3,4,5,6] wanted = [1,-2,3,-4,5,-6] I can implement it like this: input = range(3,12) wanted = [] for (i,v) in enumerate(input): if i%2 == 0: wanted.append(v) else: wanted.append(-v) >>input = range(3,12)[i%2==0 and v or -v for (i,v) in enumerate(input)] [3, -4, 5, -6, 7, -8, 9, -10, 11] But is there any other better way to do this. I'm not sure densely packing it into a list comprehension is necessarily a *better* way, just a more compact way. To make more sense of it, you might create a helper function that does your comparison work: def inv_if(v, test): if test: return v else: return -v [inv_if(v, i%2==0) for (i,v) in enumerate(input)] Or you could even do something like def inv_alternating(t): i, v = t if i%2==0: return v else: return -v [inv_alternating(t) for t in enumerate(input)] Either compacts it for the actual call within a list comprehension, but it is cleaner to read what's going on. -tkc Nov 28 '06 #3

 P: n/a jm*******@no.spam.gmail.com wrote: I have a list of numbers and I want to build another list with every second element multiplied by -1. input = [1,2,3,4,5,6] wanted = [1,-2,3,-4,5,-6] I can implement it like this: input = range(3,12) wanted = [] for (i,v) in enumerate(input): if i%2 == 0: wanted.append(v) else: wanted.append(-v) But is there any other better way to do this. Use slices: input[1::2] = [-item for item in input[1::2]] If you don't want to do it in-place, just make a copy: wanted = input[:] wanted[1::2] = [-item for item in wanted[1::2]] -- Leo Nov 28 '06 #4

 P: n/a On 2006-11-28, jm*******@no.spam.gmail.com

 P: n/a Wow, I was in fact searching for this syntax in the python tutorial. It is missing there. Is there a reference page which documents all possible list comprehensions. -- Suresh Leo Kislov wrote: jm*******@no.spam.gmail.com wrote: I have a list of numbers and I want to build another list with every second element multiplied by -1. input = [1,2,3,4,5,6] wanted = [1,-2,3,-4,5,-6] I can implement it like this: input = range(3,12) wanted = [] for (i,v) in enumerate(input): if i%2 == 0: wanted.append(v) else: wanted.append(-v) But is there any other better way to do this. Use slices: input[1::2] = [-item for item in input[1::2]] If you don't want to do it in-place, just make a copy: wanted = input[:] wanted[1::2] = [-item for item in wanted[1::2]] -- Leo Nov 28 '06 #6

 P: n/a jm*******@no.spam.gmail.com wrote: I have a list of numbers and I want to build another list with every second element multiplied by -1. [...] But is there any other better way to do this. I think the best way is the one that uses slices, as somebody suggested in this thread. This is another (worse) way, just for fun: >>from itertools import cycleinput = [1, 2, 3, 4, 5, 6]wanted = [x * sign for x, sign in zip(input, cycle([1, -1]))]wanted [1, -2, 3, -4, 5, -6] Cheers, -- Roberto Bonvallet Nov 28 '06 #7

 P: n/a On Tue, 28 Nov 2006 02:38:09 -0800, jm*******@no.spam.gmail.com wrote: I have a list of numbers and I want to build another list with every second element multiplied by -1. input = [1,2,3,4,5,6] wanted = [1,-2,3,-4,5,-6] I can implement it like this: input = range(3,12) wanted = [] for (i,v) in enumerate(input): if i%2 == 0: wanted.append(v) else: wanted.append(-v) But is there any other better way to do this. Lots of ways. Other people have given you some solutions. In my opinion, this is the simplest method of all, if you want to modify input in place: for i in range(1, len(input), 2): input[where] = -input[where] Here's another method that only works if there are an even number of items: A = input[0::2] # extended slicing B = input[1::2] B = [-x for x in B] tmp = zip(A, B) # but watch out for odd number of items! result = [] for t in tmp: result.extend(t) Here's a third method: factors = [(-1)**i for i in range(len(input))] output = map(operator.mul, input, factors) As for which is best, I leave that to you to decide. -- Steven. Nov 28 '06 #8

 P: n/a jm*******@no.spam.gmail.com wrote: Wow, I was in fact searching for this syntax in the python tutorial. It is missing there. Is there a reference page which documents all possible list comprehensions. There is actually only two forms of list comprehensions: http://docs.python.org/ref/lists.html [blah for x in expr] and [blah for x in expr if cond] And here is reference page for slicing (note, it's not list comprehension): http://docs.python.org/ref/slicings.html -- Leo Nov 28 '06 #9

 P: n/a Leo Kislov: input[1::2] = [-item for item in input[1::2]] If you don't want to do it in-place, just make a copy: wanted = input[:] wanted[1::2] = [-item for item in wanted[1::2]] Very nice solution. I have tried few versions like: from itertools import imap, islice from operator import neg 1) data[1::2] = [-el for el in data[1::2]] 2) data[1::2] = map(neg, data[1::2]) 3) data[1::2] = imap(neg, data[1::2]) 4) data[1::2] = map(neg, islice(data, 1, None, 2)) 5) etc. With Python 2.5 it seems that the n.2 (map + slicing) is the faster. Bye, bearophile Nov 28 '06 #10

### This discussion thread is closed

Replies have been disabled for this discussion.