HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonModerate

Splitting a list by indexes

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
listsplittingindexes

Problem

I am trying to build an efficient function for splitting a list of any size by any given number of indices. This method works and it took me a few hours to get it right (I hate how easy it is to get things wrong when using indexes).

Am I over-thinking this? Can you help me minimize the code? I am just not seeing it. ALSO, is there any way to simplify the input of so many variables such as in this situation?

def lindexsplit(List,*lindex):

    index = list(lindex)

    index.sort()

    templist1 = []
    templist2 = []
    templist3 = []

    breakcounter = 0
    itemcounter = 0
    finalcounter = 0

    numberofbreaks = len(index)
    totalitems = len(List)

    lastindexval = index[(len(index)-1)]
    finalcounttrigger = (totalitems-(lastindexval+1))

    for item in List:

        itemcounter += 1

        indexofitem = itemcounter - 1

        nextbreakindex = index[breakcounter]

        #Less than the last cut
        if breakcounter = lastindexval and indexofitem < totalitems + 1:

                        finalcounter += 1

                        templist3.append(item)

                        if finalcounter == finalcounttrigger:

                            templist2.append(templist3)

    return templist2


Example:

mylist = [1,2,3,4,5,6,7,8,9,0,10,11,12,13,14,15]
lindexsplit(mylist,3,5,8)
return [[1, 2, 3, 4], [5, 6], [7, 8, 9], [0, 10, 11, 12, 13, 14, 15]]

Solution

There is a lot simpler way to do this. You can use list slicing and the zip function.

List slicing essentially cuts up a given list into sections. The general form is list[start:stop:step]. The start section of a slice designates the first index of the list we want to included in our slice. The stop section designates the first index of the list we want excluded in our slice. The step section defines how many indices we are moving as well as in which direction (based on whether it is positive or negative). An example:

>>> x = [1, 2, 3, 4]
>>> x[1:3]
[2, 3]
>>> x[2:]
[3, 4]
>>> x[0:4]
[1, 2, 3, 4]
>>> x[0:4:1]
[1, 2, 3, 4]
>>> x[0:4:2]
[1, 3]
>>> x[0:4:3]
[1, 4]
>>> x[0:4:4]
[1]
>>> x[0:4:5]
[1]


The zip function takes sequences and creates a zip object that contains tuples of their corresponding index elements:

>>> for pair in zip([1, 2, 3], ['a', 'b', 'c']):
...    print(pair)
(1, 'a')
(2, 'b')
(3, 'c')


You can combine these two strategies to simplify your function. Here is my version of your lindexsplit function:

def lindexsplit(some_list, *args):
    # Checks to see if any extra arguments were passed. If so,
    # prepend the 0th index and append the final index of the 
    # passed list. This saves from having to check for the beginning
    # and end of args in the for-loop. Also, increment each value in 
    # args to get the desired behavior.
    if args:
        args = (0,) + tuple(data+1 for data in args) + (len(some_list)+1,)

    # For a little more brevity, here is the list comprehension of the following
    # statements:
    #    return [some_list[start:end] for start, end in zip(args, args[1:])]
    my_list = []
    for start, end in zip(args, args[1:]):
        my_list.append(some_list[start:end])
    return my_list

Code Snippets

>>> x = [1, 2, 3, 4]
>>> x[1:3]
[2, 3]
>>> x[2:]
[3, 4]
>>> x[0:4]
[1, 2, 3, 4]
>>> x[0:4:1]
[1, 2, 3, 4]
>>> x[0:4:2]
[1, 3]
>>> x[0:4:3]
[1, 4]
>>> x[0:4:4]
[1]
>>> x[0:4:5]
[1]
>>> for pair in zip([1, 2, 3], ['a', 'b', 'c']):
...    print(pair)
(1, 'a')
(2, 'b')
(3, 'c')
def lindexsplit(some_list, *args):
    # Checks to see if any extra arguments were passed. If so,
    # prepend the 0th index and append the final index of the 
    # passed list. This saves from having to check for the beginning
    # and end of args in the for-loop. Also, increment each value in 
    # args to get the desired behavior.
    if args:
        args = (0,) + tuple(data+1 for data in args) + (len(some_list)+1,)

    # For a little more brevity, here is the list comprehension of the following
    # statements:
    #    return [some_list[start:end] for start, end in zip(args, args[1:])]
    my_list = []
    for start, end in zip(args, args[1:]):
        my_list.append(some_list[start:end])
    return my_list

Context

StackExchange Code Review Q#47868, answer score: 17

Revisions (0)

No revisions yet.