Velocity Reviews > spliting a list by nth items

# spliting a list by nth items

Steven Bethard
Guest
Posts: n/a

 09-23-2004
I feel like this has probably been answered before, but I couldn't
find something quite like it in the archives. Feel free to point me

I have a list in a particular order that I want to split into two
lists: the list of every nth item, and the list of remaining items.
It's important to maintain the original order in both lists.

So the first list is simple:

nth_items = items[::n]

The second list is what's giving me trouble. So far, the best I've
come up with is:

non_nth_items = list(items)
del non_nth_items[::n]

Is this the right way to do this?

Steve
--
You can wordify anything if you just verb it.
- Bucky Katt, Get Fuzzy

Peter Hansen
Guest
Posts: n/a

 09-23-2004
Steven Bethard wrote:
> I feel like this has probably been answered before, but I couldn't
> find something quite like it in the archives. Feel free to point me
>
> I have a list in a particular order that I want to split into two
> lists: the list of every nth item, and the list of remaining items.
> It's important to maintain the original order in both lists.
>
> So the first list is simple:
>
> nth_items = items[::n]
>
> The second list is what's giving me trouble. So far, the best I've
> come up with is:
>
> non_nth_items = list(items)
> del non_nth_items[::n]
>
> Is this the right way to do this?

There's probably no "right" way. Your way isn't the way I
would have thought to do it, I think. But it's brilliant.
(Also simple and clear.)

-Peter

Michael Hoffman
Guest
Posts: n/a

 09-23-2004
Steven Bethard wrote:

> I have a list in a particular order that I want to split into two
> lists: the list of every nth item, and the list of remaining items.
> It's important to maintain the original order in both lists.
>
> So the first list is simple:
>
> nth_items = items[::n]
>
> The second list is what's giving me trouble.

non_nth_items = [x for x in items if x % n]
--
Michael Hoffman

Larry Bates
Guest
Posts: n/a

 09-23-2004
I believe you meant somthing like:

non_nth_items = [items[i-1] for i in range(1,len(items)-1) if i % n]

I don't think the "if x % n" won't work on his list of items

Larry Bates

"Michael Hoffman" <(E-Mail Removed) > wrote in
message news:civ1bq\$4qp\$(E-Mail Removed)...
> Steven Bethard wrote:
>
>> I have a list in a particular order that I want to split into two
>> lists: the list of every nth item, and the list of remaining items. It's
>> important to maintain the original order in both lists.
>>
>> So the first list is simple:
>>
>> nth_items = items[::n]
>>
>> The second list is what's giving me trouble.

>
> non_nth_items = [x for x in items if x % n]
> --
> Michael Hoffman

Michael Hoffman
Guest
Posts: n/a

 09-23-2004
Larry Bates wrote:

> I believe you meant somthing like:
>
> non_nth_items = [items[i-1] for i in range(1,len(items)-1) if i % n]
>
> I don't think the "if x % n" won't work on his list of items

D'oh! I wasn't thinking--the test list of items I used was
range(something), so of course it worked.

What I meant <wink> was:

non_nth_items = [x for index, x in enumerate(items) if index % n]

Thanks for the correction.
--
Michael Hoffman

Steven Bethard
Guest
Posts: n/a

 09-23-2004
Larry Bates <lbates <at> swamisoft.com> writes:
>
> I believe you meant somthing like:
>
> non_nth_items = [items[i-1] for i in range(1,len(items)-1) if i % n]

Yeah, the items list is not of the form range(x) -- in fact, my current use
for this is with a list of filenames -- so Michael Hoffman's solution:

> > non_nth_items = [x for x in items if x % n]

wouldn't work. In the full fledged problem, I actually have a start parameter
for the slice as well as the step parameter (n), so I could probably do
something along these lines (inspired by your two suggestions):

non_nth_items = [item for i, item in enumerate(items) if (i - start) % n]

non_nth_items = list(items)
del non_nth_items[start::n]

The enumerate/range solution is a little more verbose, but it does only go
through the list once. Thanks for the good suggestions!

STeve

Raymond Hettinger
Guest
Posts: n/a

 09-23-2004
[Steven Bethard]
> so I could probably do
> something along these lines (inspired by your two suggestions):
>
> non_nth_items = [item for i, item in enumerate(items) if (i - start) % n]
>
>
> non_nth_items = list(items)
> del non_nth_items[start::n]
>
> The enumerate/range solution is a little more verbose, but it does only go
> through the list once. Thanks for the good suggestions!

The enumerate solution has a lot going for it. It is more flexible and easily
accomodates criteria other than every nth item. More importantly, it
demonstrates an important guiding principle: multiple list deletions are a code
smell indicating that building a new list is a better approach. On this
newsgroup, I've seen people tie themselves in knots with multiple in-place
deletions during iteration when the new list approach was clearer, more robust,
and faster.

The runtime behavior of the non_nth_items[start::n] approach is implementation
dependent. One can easily imagine a O(n**2) process running behind the scenes.
CPython is a smarter than that, but the code for list_ass_subscript() in
listobject.c is not a pretty sight.

Raymond Hettinger

Steven Bethard
Guest
Posts: n/a

 09-23-2004
Raymond Hettinger writes:
> The enumerate solution has a lot going for it. It is more flexible and
> easily accomodates criteria other than every nth item.

items[start::n]
to make the nth_items list in the first place. (If I was planning to allow
for other criteria, I'd probably use filter or ifilter instead of the
slicing...)

> More importantly, it demonstrates an important guiding principle: multiple
> list deletions are a code smell indicating that building a new list is a
> better approach.

This was kinda my feeling -- hence why I posted. Part of the problem for me
was that because the two lists were so closely related semantically, I was
looking for a syntax that was also closely related. Sometimes this is a good
intuition to have, sometimes not.

> The runtime behavior of the non_nth_items[start::n] approach is
> implementation dependent.

Ahh, I didn't know that. Good thing to know...

Thanks,

Steve

Elaine Jackson
Guest
Posts: n/a

 09-24-2004
>>> x = [0,1,2,3,4,5,6,7,8,9]
>>> n = 3
>>> y = [x[i] for i in range(len(x)) if i%n==0]
>>> z = [x[i] for i in range(len(x)) if i%n<>0]
>>> x

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> y

[0, 3, 6, 9]
>>> z

[1, 2, 4, 5, 7, 8]

"Steven Bethard" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
| I feel like this has probably been answered before, but I couldn't
| find something quite like it in the archives. Feel free to point me
|
| I have a list in a particular order that I want to split into two
| lists: the list of every nth item, and the list of remaining items.
| It's important to maintain the original order in both lists.
|
| So the first list is simple:
|
| nth_items = items[::n]
|
| The second list is what's giving me trouble. So far, the best I've
| come up with is:
|
| non_nth_items = list(items)
| del non_nth_items[::n]
|
| Is this the right way to do this?
|
| Steve
| --
| You can wordify anything if you just verb it.
| - Bucky Katt, Get Fuzzy

Carlos Ribeiro
Guest
Posts: n/a

 09-24-2004
I was one of the frequent posters on the many tools/ides/gui threads
that appeared here over the past weeks. I'm now partly satisfied. My
search for a good IDE that is usable in my lowend machine is still not
completed. But I found a good setup using a free editor and PythonWin
working together.

I'm using Crimson Editor, a small freeware editor. The most
interesting part is that it isn't the most featured of all editors
I've tried; it isn't as powerful as vi or emacs, but has one feature
that I wanted the most, that is a fairly simple project management
tool. It simply allows me to organize a list of files that I'm using
for a project on the left pane. I can click on a file to open it. It's
amazingly useful when you're dealing with "hot" files stored on
several different directories, and you don't have to remember where is
it located, or to manually walk the open file dialog looking for it.

I'm using PythonWin for testing, mostly because the Windows console is
so braindead, and because PythonWin help is quick well organized (it's
about the same that you find in the web, but a little bit more
convenient).

I'm also evaluating Wing IDE 2.0; I had a few issues with it that were
solved, but for some tasks I found it too heavy for my limited
resources. Anyway, I'm keeping an eye on it.

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

--
Carlos Ribeiro
Consultoria em Projetos
blog: http://rascunhosrotos.blogspot.com
blog: http://pythonnotes.blogspot.com
mail: http://www.velocityreviews.com/forums/(E-Mail Removed)
mail: (E-Mail Removed)