slicing lists

Y

Yves Dorfsman

Is there a way to do:
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
x[0,2:6]

That would return:
[0, 3, 4, 5, 6]

I am surprised this notation is not supported, it seems intuitive.
A concrete example of the sort of thing I want to do:

p = file('/etc/passwd').readlines()
q = [ e.strip().split(':')[0,2:] for e in p ]

(getting rid of the password / x field)


Thanks.

Yves.
http://www.SollerS.ca
 
I

Ivan Illarionov

Is there a way to do:
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
x[0,2:6]

That would return:
[0, 3, 4, 5, 6]

IMHO this notation is confusing.

What's wrong with:
[0]+x[2:6]
I am surprised this notation is not supported, it seems intuitive. A
concrete example of the sort of thing I want to do:

p = file('/etc/passwd').readlines()
q = [ e.strip().split(':')[0,2:] for e in p ]

(getting rid of the password / x field)

This works and is clearer:
[[0] + e.strip().split(':')[2:] for e in open('/etc/passwd')]
 
I

Ivan Illarionov

Is there a way to do:
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
x[0,2:6]

That would return:
[0, 3, 4, 5, 6]

IMHO this notation is confusing.

What's wrong with:
[0]+x[2:6]
I am surprised this notation is not supported, it seems intuitive. A
concrete example of the sort of thing I want to do:

p = file('/etc/passwd').readlines()
q = [ e.strip().split(':')[0,2:] for e in p ]

(getting rid of the password / x field)

This works and is clearer:
[[0] + e.strip().split(':')[2:] for e in open('/etc/passwd')]

or maybe you wanted to do this:
[e.split(':')[0] for e in open('/etc/passwd')]
['root', 'daemon', 'bin', 'sys', 'sync', ...]

What are you trying to get from /etc/passwd?
 
C

castironpi

Is there a way to do:
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
x[0,2:6]
That would return:
[0, 3, 4, 5, 6]
IMHO this notation is confusing.
What's wrong with:
[0]+x[2:6]
I am surprised this notation is not supported, it seems intuitive. A
concrete example of the sort of thing I want to do:
p = file('/etc/passwd').readlines()
q = [ e.strip().split(':')[0,2:] for e in p ]
(getting rid of the password / x field)
This works and is clearer:
[[0] + e.strip().split(':')[2:] for e in open('/etc/passwd')]

or maybe you wanted to do this:
[e.split(':')[0] for e in open('/etc/passwd')]

['root', 'daemon', 'bin', 'sys', 'sync', ...]

What are you trying to get from /etc/passwd?

The t. Oughtn't there be a run on Guido's name more often than is?

You -could- write:

x[ slice(0)+slice(2,6) ]

where slice would be an 'autochaining' type under a syntax. Fine for
slices, not for logic.

x[ b1+And+b2+Or+b3 ]

would also register as b1 and b2 or b3, which really quickly rises on
the wheel again, er, um, crawls up the spout.

Would you be happy with x[ '0,2:6' ], necessarily in quotes? With two
punctuation marks you couldn't get much farther in money than Python
does today.

x[ '0 2:6' ]
-> x.__getitem__( x, '0 2:6' )
-> '0 2:6'.split( )
-> x.__getslice__( x, slice( 0 ) )
... + x.__getslice__( x, slice( 2, 6 ) )

However, it's not clear it's trivial to overwrite a built-in type's
__getitem__!
 
M

Miles

> On Wed, 07 May 2008 23:29:27 +0000, Yves Dorfsman wrote:
>
> > Is there a way to do:
> > x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
> > x[0,2:6]
> >
> > That would return:
> > [0, 3, 4, 5, 6]
>
> IMHO this notation is confusing.
>
> What's wrong with:
> [0]+x[2:6]

I think Yves meant to return [1, 3, 4, 5, 6], as in Perl's list slicing:

my @x = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
return @x[0, 2..6]; // returns (1, 3, 4, 5, 6)

This isn't incredibly efficient, but it does what you want (I think):

from itertools import chain

class multisliceable(list):
def __getitem__(self, slices):
if isinstance(slices, (slice, int, long)):
return list.__getitem__(self, slices)
else:
return list(chain(*[list.__getitem__(self, s) if isinstance(s, slice)
else [list.__getitem__(self, s)] for s in slices]))

p = open('/etc/passwd')
q = [multisliceable(e.strip().split(':'))[0,2:] for e in p]

-Miles
 
I

Ivan Illarionov

Is there a way to do:
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
x[0,2:6]

That would return:
[0, 3, 4, 5, 6]

IMHO this notation is confusing.

What's wrong with:
[0]+x[2:6]

I think Yves meant to return [1, 3, 4, 5, 6], as in Perl's list
slicing:

my @x = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10); return @x[0, 2..6]; // returns
(1, 3, 4, 5, 6)

So it should be x[0] + x[2:6] or x[0].extend(x[2:6])
 
I

Ivan Illarionov

On Wed, 07 May 2008 23:29:27 +0000, Yves Dorfsman wrote:

Is there a way to do:
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
x[0,2:6]

That would return:
[0, 3, 4, 5, 6]

IMHO this notation is confusing.

What's wrong with:
[0]+x[2:6]

I think Yves meant to return [1, 3, 4, 5, 6], as in Perl's list
slicing:

my @x = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10); return @x[0, 2..6]; //
returns (1, 3, 4, 5, 6)

So it should be x[0] + x[2:6] or x[0].extend(x[2:6])

Oh, I meant
[x[0]] + x[2:6]
or
y = [x[0]]
y.extend(x[2:6])

Sorry
 
A

attn.steven.kuo

(snipped)
I think Yves meant to return [1, 3, 4, 5, 6], as in Perl's list slicing:

my @x = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
return @x[0, 2..6]; // returns (1, 3, 4, 5, 6)

This isn't incredibly efficient, but it does what you want (I think):

from itertools import chain

class multisliceable(list):
def __getitem__(self, slices):
if isinstance(slices, (slice, int, long)):
return list.__getitem__(self, slices)
else:
return list(chain(*[list.__getitem__(self, s) if isinstance(s, slice)
else [list.__getitem__(self, s)] for s in slices]))

p = open('/etc/passwd')
q = [multisliceable(e.strip().split(':'))[0,2:] for e in p]

-Miles



There's also the operator module:

import itertools
import operator

idx = [one for one in itertools.chain([0], range(2, 6))]

wanted = operator.itemgetter(*idx)

q = [wanted(line.strip().split(':')) for line in file("/etc/passwd")]
 
Y

Yves Dorfsman

Miles said:
Is there a way to do:
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
x[0,2:6]

That would return:
[0, 3, 4, 5, 6]

Arg... Yes, this is a typo, I meant:
[1, 3, 4, 5, 6]
I think Yves meant to return [1, 3, 4, 5, 6], as in Perl's list slicing:

my @x = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
return @x[0, 2..6]; // returns (1, 3, 4, 5, 6)

Yes, exactly.
This isn't incredibly efficient, but it does what you want (I think):

from itertools import chain

class multisliceable(list):
def __getitem__(self, slices):
if isinstance(slices, (slice, int, long)):
return list.__getitem__(self, slices)
else:
return list(chain(*[list.__getitem__(self, s) if isinstance(s, slice)
else [list.__getitem__(self, s)] for s in slices]))

p = open('/etc/passwd')
q = [multisliceable(e.strip().split(':'))[0,2:] for e in p]

So would it be a worthy addition to python, to add it right in the core of
the language, and hopefully in an efficient manner ?

That would certainly help some type of list comprehensions, making them more
readable, and hopefully more readable (running split once instead of twice,
or how many number of time you need it). The passwd example is just one
example I ran into, but I can see running in this problem a lot with more
complex cases. Right now I solve the passwd pb with:

p = file('/etc/passwd').readlines()
r = [ e.strip().split(':') for e in p ]
s = [ e[0:1] + e[2:] for e in r ]


Or:

p = file('/etc/passwd').readlines()
s = [ e.strip().split(':')[0:1] + e.strip().split(':')[2:] for e in p ]

In the first case we're looping twice (two list comprehension), in the
second case we're running the split twice on every element of p.


Yves.
http://www.SollerS.ca
 
G

George Sakkis

So would it be a worthy addition to python, to add it right in the core of
the language, and hopefully in an efficient manner ?

Given that it's a straightforward generalization of the existing
slicing syntax, it sure does make sense from a theoretical standpoint.
Whether it's a worthy addition is debatable though; I don't think
there are many common use cases to convince the core developers to
work on it. OTOH if you (or someone else) comes up with a working
patch, it might improve its chances of getting accepted.

George
 
B

Boris Borcic

Yves said:
So would it be a worthy addition to python, to add it right in the core
of the language, and hopefully in an efficient manner ?

Note that the s[0,2:6] syntax is currently allowed because of the distinct
semantics that the Numeric module and its successors numarray and numpy had for it.
 
M

MRAB

Miles said:
Is there a way to do:
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
x[0,2:6]
That would return:
[0, 3, 4, 5, 6]

Arg... Yes, this is a typo, I meant:
[1, 3, 4, 5, 6]
I think Yves meant to return [1, 3, 4, 5, 6], as in Perl's list slicing:
my @x = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
return @x[0, 2..6]; // returns (1, 3, 4, 5, 6)

Yes, exactly.


This isn't incredibly efficient, but it does what you want (I think):
from itertools import chain
class multisliceable(list):
def __getitem__(self, slices):
if isinstance(slices, (slice, int, long)):
return list.__getitem__(self, slices)
else:
return list(chain(*[list.__getitem__(self, s) if isinstance(s, slice)
else [list.__getitem__(self, s)] for s in slices]))
p = open('/etc/passwd')
q = [multisliceable(e.strip().split(':'))[0,2:] for e in p]

So would it be a worthy addition to python, to add it right in the core of
the language, and hopefully in an efficient manner ?

That would certainly help some type of list comprehensions, making them more
readable, and hopefully more readable (running split once instead of twice,
or how many number of time you need it). The passwd example is just one
example I ran into, but I can see running in this problem a lot with more
complex cases. Right now I solve the passwd pb with:

p = file('/etc/passwd').readlines()
r = [ e.strip().split(':') for e in p ]
s = [ e[0:1] + e[2:] for e in r ]

Or:

p = file('/etc/passwd').readlines()
s = [ e.strip().split(':')[0:1] + e.strip().split(':')[2:] for e in p ]

In the first case we're looping twice (two list comprehension), in the
second case we're running the split twice on every element of p.
You should've read the thread entitled "Why don't generators execute
until first yield?"! :) Michael Torrie gave the URL
http://www.dabeaz.com/generators/Generators.pdf. Your example can be
rewritten as follows:

p = file('/etc/passwd') # No need for readlines() because file's
iterator yields the lines.
r = ( e.strip().split(':') for e in p ) # A generator expression
instead of a list comprehension.
s = [ e[0:1] + e[2:] for e in r ]
 
Y

Yves Dorfsman

MRAB said:
You should've read the thread entitled "Why don't generators execute
until first yield?"! :) Michael Torrie gave the URL
http://www.dabeaz.com/generators/Generators.pdf. Your example can be
rewritten as follows:

p = file('/etc/passwd') # No need for readlines() because file's
iterator yields the lines.
r = ( e.strip().split(':') for e in p ) # A generator expression
instead of a list comprehension.
s = [ e[0:1] + e[2:] for e in r ]

Thanks, this is very elegant indeed, but because there are two list
comprehension expressions (the one defining r and the one defining s), it
means that the we're looping twice over the same list instead of once with
the e[0,2:] hypotetical notation ; or am I missing something ?

Yves.
http://www.SollerS.ca
 
I

Ian Kelly

Is there a way to do:
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
x[0,2:6]

That would return:
[0, 3, 4, 5, 6]

I am surprised this notation is not supported, it seems intuitive.
A concrete example of the sort of thing I want to do:

p = file('/etc/passwd').readlines()
q = [ e.strip().split(':')[0,2:] for e in p ]

(getting rid of the password / x field)

Have a look at the itemgetter function from the operator module.

g = itemgetter( 0, *range(2, 6) )
p = file("/etc/passwd").readlines()
q = [ g( e.strip().split(':') ) for e in p ]
 
C

castironpi

Is there a way to do:
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
x[0,2:6]
That would return:
[0, 3, 4, 5, 6]
I am surprised this notation is not supported, it seems intuitive.
A concrete example of the sort of thing I want to do:
p = file('/etc/passwd').readlines()
q = [ e.strip().split(':')[0,2:] for e in p ]
(getting rid of the password / x field)

Have a look at the itemgetter function from the operator module.

g = itemgetter( 0, *range(2, 6) )
p = file("/etc/passwd").readlines()
q = [ g( e.strip().split(':') ) for e in p ]

The only thing is, is there is another natural meaning to [a,b:c].

Counting grids on the diagonals, the rational set is well defined:

0: 0, 0
1: 1, 0
2: 0, 1
3: 2, 0
4: 1, 1
5: 0, 2
6: 3, 0
7: 2, 1
...

Thencefore ( 2, 0 ) : ( 3, 0 ) is well defined. Thencefore,

a,b:c,d

is not; x[a,b:c,d]= x[a]+ x[b:c]+ x[d].
 
Y

Yves Dorfsman

The only thing is, is there is another natural meaning to [a,b:c].

Counting grids on the diagonals, the rational set is well defined:

0: 0, 0
1: 1, 0
2: 0, 1
3: 2, 0
4: 1, 1
5: 0, 2
6: 3, 0
7: 2, 1
...

Thencefore ( 2, 0 ) : ( 3, 0 ) is well defined. Thencefore,

a,b:c,d

is not; x[a,b:c,d]= x[a]+ x[b:c]+ x[d].

I'm not sure what you mean here. Could you give me a simple piece of code to
show an example ?


Yves.
http://www.SollerS.ca
 
C

castironpi

The only thing is, is there is another natural meaning to [a,b:c].
Counting grids on the diagonals, the rational set is well defined:
0: 0, 0
1: 1, 0
2: 0, 1
3: 2, 0
4: 1, 1
5: 0, 2
6: 3, 0
7: 2, 1
...
Thencefore ( 2, 0 ) : ( 3, 0 ) is well defined.  Thencefore,

is not; x[a,b:c,d]= x[a]+ x[b:c]+ x[d].

I'm not sure what you mean here. Could you give me a simple piece of code to
show an example ?

Yves.http://www.SollerS.ca- Hide quoted text -

- Show quoted text -

Yves, sadly, simple piece of code is not the writer's forte. I was
merely advising against leaping in to syntax additions, changes even.
The point was, even though a,b:c,d is shown ill-defined, a,b:c may not
be.
 
C

castironpi

The only thing is, is there is another natural meaning to [a,b:c].
Counting grids on the diagonals, the rational set is well defined:
0: 0, 0
1: 1, 0
2: 0, 1
3: 2, 0
4: 1, 1
5: 0, 2
6: 3, 0
7: 2, 1
...
Thencefore ( 2, 0 ) : ( 3, 0 ) is well defined.  Thencefore,
a,b:c,d
is not; x[a,b:c,d]= x[a]+ x[b:c]+ x[d].
I'm not sure what you mean here. Could you give me a simple piece of code to
show an example ?
- Show quoted text -

Yves, sadly, simple piece of code is not the writer's forte.  I was
merely advising against leaping in to syntax additions, changes even.
The point was, even though a,b:c,d is shown ill-defined, a,b:c may not
be.- Hide quoted text -

- Show quoted text -

Now: In the case of enumerate( rationals ), list slicing can be plenty
fine. Any use to the dirational enumerate?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,143
Latest member
SterlingLa
Top