Google Gruppi non supporta più i nuovi post o le nuove iscrizioni Usenet. I contenuti storici continuano a essere visibili.

Re: faster than list.extend()

13 visualizzazioni
Passa al primo messaggio da leggere

Chris Rebert

da leggere,
16 nov 2009, 17:41:2516/11/09
a Hyunchul Kim, pytho...@python.org
On Mon, Nov 16, 2009 at 2:30 PM, Hyunchul Kim
<hyunchul...@gmail.com> wrote:
> Hi, all.
>
> I want to improve speed of following simple function.
> Any suggestion?
>
> **********
> def triple(inputlist):
>   results = []
>   for x in inputlist:
>     results.extend([x,x,x])
>   return results
> **********

You'd probably be better off calling .append() 3 times instead of
.extend() as it would avoid the creation of all those intermediate
3-element lists.

Cheers,
Chris
--
http://blog.rebertia.com

Tim Chase

da leggere,
16 nov 2009, 17:55:5516/11/09
a Hyunchul Kim, pytho...@python.org
Hyunchul Kim wrote:
> Hi, all.
>
> I want to improve speed of following simple function.
> Any suggestion?
>
> **********
> def triple(inputlist):
> results = []
> for x in inputlist:
> results.extend([x,x,x])
> return results
> **********

Several ways occur to me:

def t1(i):
for x in i:
yield x
yield x
yield x

def t2(i):
r = range(3)
return (x for x in i for _ in r)


I prefer to return generators in case the input is large, but in
both cases, you can just wrap it in list() like

list(t1(inputlist))

or in t2(), you can just change it to use

return [x for x in i for _ in r]

-tkc


Raymond Hettinger

da leggere,
16 nov 2009, 18:28:4016/11/09
a
On Nov 16, 2:41 pm, Chris Rebert <c...@rebertia.com> wrote:
> On Mon, Nov 16, 2009 at 2:30 PM, Hyunchul Kim
>
> <hyunchul.mail...@gmail.com> wrote:
> > Hi, all.
>
> > I want to improve speed of following simple function.
> > Any suggestion?
>
> > **********
> > def triple(inputlist):
> >   results = []
> >   for x in inputlist:
> >     results.extend([x,x,x])
> >   return results


Here's an itertools variant that is somewhat speedy when the inputlist
is long:

from itertools import *

def triple3(inputlist, list=list,
chain_from_iterable=chain.from_iterable, izip=izip):
return list(chain_from_iterable(izip(inputlist, inputlist,
inputlist)))

Raymond


Gabriel Genellina

da leggere,
16 nov 2009, 21:15:0616/11/09
a pytho...@python.org
En Mon, 16 Nov 2009 19:30:27 -0300, Hyunchul Kim
<hyunchul...@gmail.com> escribi�:

> I want to improve speed of following simple function.
> Any suggestion?
>
> **********
> def triple(inputlist):
> results = []
> for x in inputlist:
> results.extend([x,x,x])
> return results

> **********

These are my best attempts:

def triple3(inputlist):
results = []
append = results.append
for x in inputlist:
append(x); append(x); append(x)
return results

def triple4(inputlist, _three=xrange(3)):
return [x for x in inputlist for _ in _three]

For a 400-items list, triple3 is 40% faster and triple4 25% faster than
yours.

--
Gabriel Genellina

Jason Sewall

da leggere,
16 nov 2009, 21:56:3116/11/09
a Raymond Hettinger, pytho...@python.org

Even (slightly) faster:

def triple3_mk2(inputlist):
return list(chain.from_iterable(izip(*repeat(inputlist, 3))))

I tried something like this when I saw Hyunchul's original email, but
I didn't know about chain.from_iterable and it was pretty slow
compared to the original. Adding (itertools.)repeat to Raymonds
speeds it up 5-10% more.

I'm pretty surprised this is faster than Tim's t2 (which is actually a
little slower than the original); I always thought of comprehensions
as the fastest way to do this find of stuff.

Jason

Peter Otten

da leggere,
17 nov 2009, 05:24:1817/11/09
a
Gabriel Genellina wrote:

> En Mon, 16 Nov 2009 19:30:27 -0300, Hyunchul Kim

> <hyunchul...@gmail.com> escribió:


>
>> I want to improve speed of following simple function.
>> Any suggestion?
>>
>> **********
>> def triple(inputlist):
>> results = []
>> for x in inputlist:
>> results.extend([x,x,x])
>> return results
>> **********
>
> These are my best attempts:
>
> def triple3(inputlist):
> results = []
> append = results.append
> for x in inputlist:
> append(x); append(x); append(x)
> return results
>
> def triple4(inputlist, _three=xrange(3)):
> return [x for x in inputlist for _ in _three]
>
> For a 400-items list, triple3 is 40% faster and triple4 25% faster than
> yours.

[I didn't see the original post]

If inputlist is actually a list or tuple the following should beat them all:

def triple_repeat(items):
result = [None] * (3*len(items))
result[::3] = result[1::3] = result[2::3] = items
return result

For small n the generalization should still be quite competitive:

def n_repeat(items, n):
items = tuple(items)
result = [None]*(len(items) * n)
for offset in range(n):
result[offset::n] = items
return result

Some measurements:

$ cat extend.py
from itertools import *

def triple_repeat(items):
result = [None] * (3*len(items))
result[::3] = result[1::3] = result[2::3] = items
return result

def n_repeat(items, n):
items = tuple(items)
result = [None]*(len(items) * n)
for offset in range(n):
result[offset::n] = items
return result

def t1(i):
for x in i:
yield x
yield x
yield x

def triple3(inputlist, list=list, chain_from_iterable=chain.from_iterable, izip=izip):
return list(chain_from_iterable(izip(inputlist, inputlist, inputlist)))

data = range(1000)


$ python -m timeit -s 'from extend import triple_repeat, data' 'triple_repeat(data)'
10000 loops, best of 3: 52.4 usec per loop
$ python -m timeit -s 'from extend import n_repeat, data' 'n_repeat(data, 3)'
10000 loops, best of 3: 60.7 usec per loop
$ python -m timeit -s 'from extend import t1, data' 'list(t1(data))'
1000 loops, best of 3: 337 usec per loop
$ python -m timeit -s 'from extend import triple3, data' 'triple3(data)'
1000 loops, best of 3: 231 usec per loop

Peter

0 nuovi messaggi