Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elegant way to slice a list with a condition

Tags:

python

list

Given a list [2,8,13,15,24,30], all the elements of which are supposed to be in range(31). Now I want to slice it into 3 lists, first list with numbers from 0 to 10, the second one with numbers from 11 to 20, and the others into the rest.

Here is my ugly code :

numbers = [2,8,13,15,24,30]
mylist = [[],[],[]] # I hate this the most...
for i in numbers:
    if i <= 10 :
        mylist[0].append(i)
    elif i > 10 and i <= 20:
        mylist[1].append(i)
    else:
        mylist[2].append(i)

print mylist

I don't think this is a good way to do it. Any suggestions please?

like image 582
hajimuz Avatar asked Aug 21 '14 16:08

hajimuz


People also ask

How do you slice a list with condition in python?

split() , to split the list into an ordered collection of consecutive sub-lists. E.g. split([1,2,3,4,5,3,6], 3) -> ([1,2],[4,5],[6]) , as opposed to dividing a list's elements by category.

Can a string slice expression be used on a list?

Slices for strings and tuples So far, we have shown examples of lists ( list type), but slices can be used with other sequence objects such as strings str and tuples tuple as well. However, str and tuple are immutable, so new values cannot be assigned.

Can you slice a list?

As well as using slicing to extract part of a list (i.e. a slice on the right hand sign of an equal sign), you can set the value of elements in a list by using a slice on the left hand side of an equal sign. In python terminology, this is because lists are mutable objects, while strings are immutable.

Can a list be sliced in Python?

In short, slicing is a flexible tool to build new lists out of an existing list. Python supports slice notation for any sequential data type like lists, strings, tuples, bytes, bytearrays, and ranges.


1 Answers

Since your input is sorted you can do this in one pass with itertools.groupby:

from itertools import groupby

[list(g) for _,g in groupby(numbers, lambda x: x//10)]
Out[3]: [[2, 8], [13, 15], [24, 26]]

No need to initialize a bunch of lists this way, groupby yields them on the fly.

This may be off-by-one in terms of how you wanted to treat the modulo-10 boundaries; if it's unclear you can always define your own grouper function:

def grouper(x):
    '''bins matching the semantics:
    [0,10] (10,20] (20, 30]'''
    return (x-1)//10 if x > 0 else 0

and use it thusly:

numbers = [2,8,13,15,24,30]

[list(g) for _,g in groupby(numbers, grouper)]
Out[5]: [[2, 8], [13, 15], [24, 30]]
like image 100
roippi Avatar answered Sep 27 '22 17:09

roippi