Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Modifying every alternate element of a sequence

Reply
Thread Tools

Modifying every alternate element of a sequence

 
 
jm.suresh@no.spam.gmail.com
Guest
Posts: n/a
 
      11-28-2006
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

 
Reply With Quote
 
 
 
 
Tim Chase
Guest
Posts: n/a
 
      11-28-2006
> 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





 
Reply With Quote
 
 
 
 
John Hicken
Guest
Posts: n/a
 
      11-28-2006

http://www.velocityreviews.com/forums/(E-Mail Removed) 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

 
Reply With Quote
 
Leo Kislov
Guest
Posts: n/a
 
      11-28-2006

(E-Mail Removed) 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

 
Reply With Quote
 
Antoon Pardon
Guest
Posts: n/a
 
      11-28-2006
On 2006-11-28, (E-Mail Removed) <(E-Mail Removed)> 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.


Wether this is better, I'll leave that for others to decide. But this
is a possibility:

wanted = [ (1 - 2*(i%2)) * item for i, item in enumerate(input)]

--
Antoon Pardon
 
Reply With Quote
 
jm.suresh@no.spam.gmail.com
Guest
Posts: n/a
 
      11-28-2006
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:
> (E-Mail Removed) 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


 
Reply With Quote
 
Roberto Bonvallet
Guest
Posts: n/a
 
      11-28-2006
(E-Mail Removed) 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 cycle
>>> input = [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
 
Reply With Quote
 
Steven D'Aprano
Guest
Posts: n/a
 
      11-28-2006
On Tue, 28 Nov 2006 02:38:09 -0800, (E-Mail Removed) 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.

 
Reply With Quote
 
Leo Kislov
Guest
Posts: n/a
 
      11-28-2006
(E-Mail Removed) 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

 
Reply With Quote
 
bearophileHUGS@lycos.com
Guest
Posts: n/a
 
      11-28-2006
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

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
how to Update/insert an xml element's text----> (<element>text</element>) HANM XML 2 01-29-2008 03:31 PM
code check for modifying sequence while iterating over it? Neal Becker Python 1 09-02-2007 05:13 PM
what's 'alternate' in <link rel=alternate>? Chris ASP .Net 2 03-04-2007 04:45 PM
Alternate initializers or alternate class? transfire@gmail.com Ruby 10 07-17-2006 03:20 AM
Alternate to Sequence? Sean Burns XML 1 01-23-2006 07:48 PM



Advertisments