Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Slice a list of lists?

109 views
Skip to first unread message

Jonno

unread,
Sep 8, 2010, 2:55:50 PM9/8/10
to pytho...@python.org
I know that I can index into a list of lists like this:
a=[[1,2,3],[4,5,6],[7,8,9]]
a[0][2]=3
a[2][0]=7

but when I try to use fancy indexing to select the first item in each
list I get:
a[0][:]=[1,2,3]
a[:][0]=[1,2,3]

Why is this and is there a way to select [1,4,7]?

Andreas Waldenburger

unread,
Sep 8, 2010, 3:08:11 PM9/8/10
to
On Wed, 8 Sep 2010 13:55:50 -0500 Jonno <jonnoj...@gmail.com> wrote:

> I know that I can index into a list of lists like this:
> a=[[1,2,3],[4,5,6],[7,8,9]]
> a[0][2]=3
> a[2][0]=7
>
> but when I try to use fancy indexing to select the first item in each
> list I get:

Let me write out in words what you're doing, and it should become clear:

> a[0][:]=[1,2,3]
Here you're making a list of all elements of the first element of a.

> a[:][0]=[1,2,3]
>
And here you're selecting the first element of all elements of a.

Huh. Not quite as clear as I hoped. But ponder on this for a few
moments. It'll dawn on you eventually.


> Why is this and is there a way to select [1,4,7]?

zip(*a)[0]

(or rather list(zip(*a)[0]), if you definitely need a list and not a
tuple)


/W

--
INVALID? DE!

Andreas Waldenburger

unread,
Sep 8, 2010, 3:12:30 PM9/8/10
to
Let me rephrase what I wrote a bit.

On Wed, 8 Sep 2010 15:08:11 -0400 Andreas Waldenburger
<use...@geekmail.INVALID> wrote:

> > a[0][:]=[1,2,3]
> Here you're making a list of all elements of the first element of a.
>

That is, you're making a copy of the first element of a.


> > a[:][0]=[1,2,3]
> >
> And here you're selecting the first element of all elements of a.
>

That is, you're taking the first element of a copy of a.

I hope this is a little less confusing.

/W

--
INVALID? DE!

Benjamin Kaplan

unread,
Sep 8, 2010, 3:11:51 PM9/8/10
to pytho...@python.org
On Wed, Sep 8, 2010 at 2:55 PM, Jonno <jonnoj...@gmail.com> wrote:
> I know that I can index into a list of lists like this:
> a=[[1,2,3],[4,5,6],[7,8,9]]
> a[0][2]=3
> a[2][0]=7
>
> but when I try to use fancy indexing to select the first item in each
> list I get:
> a[0][:]=[1,2,3]
> a[:][0]=[1,2,3]
>
> Why is this and is there a way to select [1,4,7]?
> --

It's not fancy indexing. It's called taking a slice of the existing
list. Look at it this way
a[0] means take the first element of a. The first element of a is [1,2,3]
a[0][:] means take all the elements in that first element of a. All
the elements of [1,2,3] are [1,2,3].

a[:] means take all the elements of a. So a[:] is [[1,2,3],[4,5,6],[7,8,9]].
a[:][0] means take the first element of all the elements of a. The
first element of a[:] is [1,2,3].

There is no simple way to get [1,4,7] because it is just a list of
lists and not an actual matrix. You have to extract the elements
yourself.

col = []
for row in a:
col.append(row[0])


You can do this in one line using a list comprehension:
[ row[0] for row in a ]


> http://mail.python.org/mailman/listinfo/python-list
>

Andreas Waldenburger

unread,
Sep 8, 2010, 3:17:08 PM9/8/10
to
On Wed, 8 Sep 2010 15:11:51 -0400 Benjamin Kaplan
<benjami...@case.edu> wrote:

> There is no simple way to get [1,4,7] because it is just a list of
> lists and not an actual matrix. You have to extract the elements
> yourself.
>
> col = []
> for row in a:
> col.append(row[0])
>
>
> You can do this in one line using a list comprehension:
> [ row[0] for row in a ]

I would suggest this (esp. the list comprehension version) over my
suggestion of zip(). WAAAYYYY more readable. Apparently I'm getting
rusty.

/W

--
INVALID? DE!

Emile van Sebille

unread,
Sep 8, 2010, 3:51:41 PM9/8/10
to pytho...@python.org
On 9/8/2010 12:17 PM Andreas Waldenburger said...

zip is very handy for inverting rows and cols (x's and y's, whatever)

>>> a = [(1,2),(3,4),(5,6),(7,8),(9,10)]
>>> zip(*a)
[(1, 3, 5, 7, 9), (2, 4, 6, 8, 10)]

So, I like zip if you're dealing with a in a matrix-ish manner, and list
comps for picking selected items out of a list.

Emile

Jonno

unread,
Sep 8, 2010, 4:06:15 PM9/8/10
to pytho...@python.org
On Wed, Sep 8, 2010 at 2:11 PM, Benjamin Kaplan
<benjami...@case.edu> wrote:
> On Wed, Sep 8, 2010 at 2:55 PM, Jonno <jonnoj...@gmail.com> wrote:
>> I know that I can index into a list of lists like this:
>> a=[[1,2,3],[4,5,6],[7,8,9]]
>> a[0][2]=3
>> a[2][0]=7
>>
>> but when I try to use fancy indexing to select the first item in each
>> list I get:
>> a[0][:]=[1,2,3]
>> a[:][0]=[1,2,3]
>>
>> Why is this and is there a way to select [1,4,7]?
>> --
>
> It's not fancy indexing. It's called taking a slice of the existing
> list. Look at it this way
> a[0] means take the first element of a. The first element of a is [1,2,3]
> a[0][:] means take all the elements in that first element of a. All
> the elements of [1,2,3] are [1,2,3].
>
> a[:] means take all the elements of a. So a[:] is [[1,2,3],[4,5,6],[7,8,9]].
> a[:][0] means take the first element of all the elements of a. The
> first element of a[:] is [1,2,3].
>
> There is no simple way to get [1,4,7] because it is just a list of
> lists and not an actual matrix. You have to extract the elements
> yourself.
>
> col = []
> for row in a:
>    col.append(row[0])
>
>
> You can do this in one line using a list comprehension:
> [ row[0] for row in a ]
>
Thanks! (to Andreas too). Totally makes sense now.

Jonno

unread,
Sep 8, 2010, 4:18:56 PM9/8/10
to pytho...@python.org

Now if I want to select the first item in every 2nd item of list a
(ie: [1,7]) can I use ::2 anywhere or do I need to create a list of
indices to use in a more complex for loop?

Jonno

unread,
Sep 8, 2010, 4:23:35 PM9/8/10
to pytho...@python.org
Seems like the simplest way would be:
[row[0] for row in a][::2]

Terry Reedy

unread,
Sep 8, 2010, 4:27:02 PM9/8/10
to pytho...@python.org
On 9/8/2010 2:55 PM, Jonno wrote:
> I know that I can index into a list of lists like this:
> a=[[1,2,3],[4,5,6],[7,8,9]]
> a[0][2]=3
> a[2][0]=7
>
> but when I try to use fancy indexing to select the first item in each
> list I get:
> a[0][:]=[1,2,3]
> a[:][0]=[1,2,3]
>
> Why is this and is there a way to select [1,4,7]?

You are trying to look at a list of lists as an array and have
discovered where the asymmetry of the former makes the two
non-equivalent. To slice multi-dimensional arrays any which way, you
need an appropriate package, such as numpy.

--
Terry Jan Reedy

Benjamin Kaplan

unread,
Sep 8, 2010, 4:28:51 PM9/8/10
to pytho...@python.org
On Wed, Sep 8, 2010 at 4:23 PM, Jonno <jonnoj...@gmail.com> wrote:
> On Wed, Sep 8, 2010 at 3:18 PM, Jonno <jonnoj...@gmail.com> wrote:
>> On Wed, Sep 8, 2010 at 3:06 PM, Jonno <jonnoj...@gmail.com> wrote:
>>> On Wed, Sep 8, 2010 at 2:11 PM, Benjamin Kaplan
>>> <benjami...@case.edu> wrote:
>>>> On Wed, Sep 8, 2010 at 2:55 PM, Jonno <jonnoj...@gmail.com> wrote:
>>>>> I know that I can index into a list of lists like this:
>>>>> a=[[1,2,3],[4,5,6],[7,8,9]]
>>>>> a[0][2]=3
>>>>> a[2][0]=7
>>>>>
>>>>> but when I try to use fancy indexing to select the first item in each
>>>>> list I get:
>>>>> a[0][:]=[1,2,3]
>>>>> a[:][0]=[1,2,3]
>>>>>
>>>>> Why is this and is there a way to select [1,4,7]?
>>>>> --
>>>>
>>>> It's not fancy indexing. It's called taking a slice of the existing
>>>> list. Look at it this way
>>>> a[0] means take the first element of a. The first element of a is [1,2,3]
>>>> a[0][:] means take all the elements in that first element of a. All
>>>> the elements of [1,2,3] are [1,2,3].
>>>>
>>>> a[:] means take all the elements of a. So a[:] is [[1,2,3],[4,5,6],[7,8,9]].
>>>> a[:][0] means take the first element of all the elements of a. The
>>>> first element of a[:] is [1,2,3].
>>>>
>>>> There is no simple way to get [1,4,7] because it is just a list of
>>>> lists and not an actual matrix. You have to extract the elements
>>>> yourself.
>>>>
>>>> col = []
>>>> for row in a:
>>>>    col.append(row[0])
>>>>
>>>>
>>>> You can do this in one line using a list comprehension:
>>>> [ row[0] for row in a ]
>>>>
>>> Thanks! (to Andreas too). Totally makes sense now.
>>>
>>
>> Now if I want to select the first item in every 2nd item of list a
>> (ie: [1,7]) can I use ::2 anywhere or do I need to create a list of
>> indices to use in a more complex for loop?
>>
> Seems like the simplest way would be:
> [row[0] for row in a][::2]

Yes. You could either do that, or do
[row[0] for row in a[::2]]. It doesn't make that much of a difference,
unless memory is really tight (doing the ::2 first means your list is
smaller to begin with)

> --
> http://mail.python.org/mailman/listinfo/python-list
>

Andreas Waldenburger

unread,
Sep 8, 2010, 4:44:52 PM9/8/10
to
On Wed, 8 Sep 2010 15:23:35 -0500 Jonno <jonnoj...@gmail.com> wrote:

> On Wed, Sep 8, 2010 at 3:18 PM, Jonno <jonnoj...@gmail.com> wrote:

> [snip]


> > Now if I want to select the first item in every 2nd item of list a
> > (ie: [1,7]) can I use ::2 anywhere or do I need to create a list of
> > indices to use in a more complex for loop?
> >
> Seems like the simplest way would be:
> [row[0] for row in a][::2]

What you're doing here is selecting every second item of the list of
first items of the items in a, not the first items of every second item
in a (head spinning yet?).

If I'm not completely mindbent right now, these are logically
equivalent, but not computationally.

Compare
[row[0] for row in a][::2] # (your Python code)
with
[row[0] for row in a[::2]] # (as per your description)

The first one is more work for your computer, because it'll pick out
the first elements of *all* of the items in a, whereas the second only
picks out the first elements of every second item in a (which is only
half the amount of "picks" compared to the former).

I just thought I'd mention it. Because it might make a difference in
one of your programs some day. And because I'm a pedant ;).

/W

--
INVALID? DE!

Jonno

unread,
Sep 8, 2010, 4:54:44 PM9/8/10
to pytho...@python.org

Thanks again. It is nice to know how to do things properly even though
in my case it probably won't make much difference.

Terry, I would have used numpy arrays (I actually use them later in
the code) except the lists in my list aren't all of the same length.

Robert Kern

unread,
Sep 8, 2010, 5:26:15 PM9/8/10
to pytho...@python.org
On 9/8/10 3:27 PM, Terry Reedy wrote:

> On 9/8/2010 2:55 PM, Jonno wrote:
>> I know that I can index into a list of lists like this:
>> a=[[1,2,3],[4,5,6],[7,8,9]]
>> a[0][2]=3
>> a[2][0]=7
>>
>> but when I try to use fancy indexing to select the first item in each
>> list I get:
>> a[0][:]=[1,2,3]
>> a[:][0]=[1,2,3]
>>
>> Why is this and is there a way to select [1,4,7]?
>
> You are trying to look at a list of lists as an array and have discovered where
> the asymmetry of the former makes the two non-equivalent. To slice
> multi-dimensional arrays any which way, you need an appropriate package, such as
> numpy.

A motivating example:

[~]
|1> import numpy

[~]
|2> a = numpy.array([[1,2,3],[4,5,6],[7,8,9]])

[~]
|3> a

array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])

[~]
|4> a[0,2]
3

[~]
|5> a[2,0]
7

[~]
|6> a[0,:]
array([1, 2, 3])

[~]
|7> a[:,0]
array([1, 4, 7])


--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco

Mark Lawrence

unread,
Sep 9, 2010, 12:13:22 PM9/9/10
to pytho...@python.org
On 08/09/2010 21:23, Jonno wrote:
> On Wed, Sep 8, 2010 at 3:18 PM, Jonno<jonnoj...@gmail.com> wrote:
>> On Wed, Sep 8, 2010 at 3:06 PM, Jonno<jonnoj...@gmail.com> wrote:
>>> On Wed, Sep 8, 2010 at 2:11 PM, Benjamin Kaplan
>>> <benjami...@case.edu> wrote:
>>>> On Wed, Sep 8, 2010 at 2:55 PM, Jonno<jonnoj...@gmail.com> wrote:
>>>>> I know that I can index into a list of lists like this:
>>>>> a=[[1,2,3],[4,5,6],[7,8,9]]
>>>>> a[0][2]=3
>>>>> a[2][0]=7
>>>>>
>>>>> but when I try to use fancy indexing to select the first item in each
>>>>> list I get:
>>>>> a[0][:]=[1,2,3]
>>>>> a[:][0]=[1,2,3]
>>>>>
>>>>> Why is this and is there a way to select [1,4,7]?
>>>>> --
>>>>
>>>> It's not fancy indexing. It's called taking a slice of the existing
>>>> list. Look at it this way
>>>> a[0] means take the first element of a. The first element of a is [1,2,3]
>>>> a[0][:] means take all the elements in that first element of a. All
>>>> the elements of [1,2,3] are [1,2,3].
>>>>
>>>> a[:] means take all the elements of a. So a[:] is [[1,2,3],[4,5,6],[7,8,9]].
>>>> a[:][0] means take the first element of all the elements of a. The
>>>> first element of a[:] is [1,2,3].
>>>>
>>>> There is no simple way to get [1,4,7] because it is just a list of
>>>> lists and not an actual matrix. You have to extract the elements
>>>> yourself.
>>>>
>>>> col = []
>>>> for row in a:
>>>> col.append(row[0])
>>>>
>>>>
>>>> You can do this in one line using a list comprehension:
>>>> [ row[0] for row in a ]
>>>>
>>> Thanks! (to Andreas too). Totally makes sense now.
>>>
>>
>> Now if I want to select the first item in every 2nd item of list a
>> (ie: [1,7]) can I use ::2 anywhere or do I need to create a list of
>> indices to use in a more complex for loop?
>>
> Seems like the simplest way would be:
> [row[0] for row in a][::2]

The fastest way to find out is probably typing at the interactive
prompt. Just jump in at the deep end and see what happens. Then wait
until someone tells you to use the timeit module.

Cheers.

Mark Lawrence.

Jonno

unread,
Sep 9, 2010, 12:33:45 PM9/9/10
to pytho...@python.org
On Thu, Sep 9, 2010 at 10:58 AM, Robert Kern <rober...@gmail.com> wrote:
> Please keep responses on the mailing list. However, I will reply below
> this one time.
>
> On Thu, Sep 9, 2010 at 10:35, Jonno <jonnoj...@gmail.com> wrote:
>> Thanks Robert. I'm actually much more familiar and comfortable with
>> arrays so I know how to slice them. The problem is that the data comes
>> from lines in a file which are not all of equal length.
>> My understanding is that I need to manipulate the data as lists until
>> I can get all the lists of equal length at which point I can make an
>> array from it.
>
> If you have ragged arrays, then you do not want to slice down columns
> to begin with. You might run into a row that does not have a value at
> that column. If you need to slice down columns (whether the object
> remains a list of lists or a numpy array), then you need to create a
> rectangular array regardless. Do that first, then I recommend using
> numpy arrays. Slicing down columns (probably) won't help you with
> that.

Understood. My data actually has 2 features which make it
non-rectangular in most circumstances. One is the extra element at the
start of every nth line (I now know how to remove that) and the second
is that some lines contain more data than others. My data is
essentially a m,m,n array but data from each row is shifted to the
next line when the line is full (4 columns). A new row then starts a
new line.

I want to pick out the data and assign it to an array but I'm
wondering whether I should first try to take the data on the extra
lines, remove it and stick it on the end of the original line (the
data from one "row" could extend onto multiple lines). Or whether I'm
better trying to create the array using loops to index my way through
the lines the way they already are laid out. Hope this makes sense.

0 new messages