2one
2one

Reputation: 1085

Split a list into sub-lists based on index ranges

How do I split a list into sub-lists based on index ranges?

e.g. original list:

list1 = [x,y,z,a,b,c,d,e,f,g]

using index ranges 0–4:

list1a = [x,y,z,a,b]

using index ranges 5–9:

list1b = [c,d,e,f,g]

I already known the (variable) indices of list elements which contain certain string and want to split the list based on these index values.

Also need to split into variable number of sub-lists, i.e.:

list1a
list1b
.
.
list1[x]

Upvotes: 38

Views: 208942

Answers (10)

Practical
Practical

Reputation: 11

Update May 2023: Option 'fine' integrated.

Update Apr. 2023: Thank you Donna for your comment! I did some changes, like you suggested, but i think that it's a pretty easy example to have more precise information how it works.

The 'slieced' function is maybe a better solution for very long sequencies then the others i saw 'cause you slice the rest of the sequence not the whole again.

It's better to use Sequence_T instead of Sequence 'cause later you can complement the variables with proper commands depending of the sequence-types 'list' or 'tuple' (E.g.: append to a list)

from collections.abc import Sequence
from typing import Iterable, TypeVar, Final

Sequence_T: Final = TypeVar('Sequence_T', bound=Sequence)

def cuted(seq: Sequence_T, index: int) -> tuple[Sequence_T, Sequence_T]:
    """ Cuted in two slieces. Works with minus-index as well. """
    return seq[:index], seq[index:]

def sliced(seq: Sequence_T, indexes: Iterable[int], fine=False) -> list[Sequence_T]:
    """
    Works like cuted in two, but this can sliece the sequence multiple times.
    If you wanna fine sliecies, turn fine=True.
    Then one slice will appear not in a sequence any more.
    Take care of the maximum length of sequence that no empty sequences appear inside the result.
    """

    def checked(a_seq: Sequence_T):
        return a_seq[0] if len(a_seq) == 1 else a_seq

    def as_it_is(a_seq: Sequence_T):
        return a_seq

    if fine:
        f = checked
    else:
        f = as_it_is
    previous_i = 0
    result = []
    for i in indexes:
        seq2 = cuted(seq, i-previous_i)
        result.append(f(seq2[0]))
        seq = seq2[1]
        previous_i = i
    result.append(f(seq))
    return result

t = (1, 2, 3, 4, 5)
print(cut(t, 3)) # Output: ((1, 2, 3), (4, 5))
print(sliced(t, (-3,-2))) # Output: [(1, 2), (3,), (4, 5)]
print(sliced(t, (2,3))) # Output: [(1, 2), (3,), (4, 5)]
print(sliced(t, (2,3), True)) # Output: [(1, 2), 3, (4, 5)]
print(sliced(t, t[:-1], True)) # Output: [1, 2, 3, 4, 5]
print(sliced(t, cut(t, -1)[0], True)) # Output: [1, 2, 3, 4, 5]
print(sliced(t, t, True)) # No good output: [1, 2, 3, 4, 5, ()]
        

Upvotes: 1

Practical
Practical

Reputation: 11

from collections.abc import Sequence, Iterator
from typing import TypeVar, Final

Sequence_T: Final = TypeVar('Sequence_T', bound=Sequence)

def cuted(seq: Sequence_T, index: int) -> tuple[Sequence_T, Sequence_T]:
    """ Cuted in two slieces. Works with minus-index as well. """
    return seq[:index], seq[index:]

def sliced(seq: Sequence_T, distance: int) -> Iterator[Sequence_T]:
    """
    Works like cuted in two, but this can slice the sequence multiple times 
    and results a Iterator.
    """
    while len(seq) >= distance:
        x, seq = cuted(seq, distance)
        yield x

def sliced_i(seq: Sequence_T, indexes: Sequence[int]) -> Iterator[Sequence_T]:
    """
    Works like sliced, but this can slice the sequence in different 
    kind of slices depending on the indexes.
    """
    previous_i = 0
    for i in indexes:
        x, seq = cuted(seq, i - previous_i)
        yield x
        previous_i = i
    yield seq

Upvotes: 0

Vincenzooo
Vincenzooo

Reputation: 2401

This is the way I do it, if the input is a list of indices on which to split an array:

#input
list1 = ['x','y','z','a','b','c','d','e','f','g']
split_points = [2,5,8] 

#split array on indices:
s = split_points+[len(list1)]  #must contain index beyond last element, alternatively use directly split_points.append(len(list1))
print([list1[i1:i2] for i1,i2 in zip([0]+s[:-1],s)])

>>> [['x', 'y'], ['z', 'a', 'b'], ['c', 'd', 'e'], ['f', 'g']]

Upvotes: 1

Milana
Milana

Reputation: 91

One of the ways to do it if you have multiple indexes or know the range of indexes you need to get:

split_points - points where you will split your string or list

k - the range you need to split, example = 3

split_points = [i for i in range(0, len(string), k)]

parts = [string[ind:ind + k] for ind in split_points]

Upvotes: 4

Shady
Shady

Reputation: 246

Consider the core pesudocode of the following example:

def slice_it(list_2be_sliced, indices):
    """Slices a list at specific indices into constituent lists.
    """
    indices.append(len(list_2be_sliced))
    return [list_2be_sliced[indices[i]:indices[i+1]] for i in range(len(indices)-1)]

Upvotes: 1

TerryA
TerryA

Reputation: 59974

In python, it's called slicing. Here is an example of python's slice notation:

>>> list1 = ['a','b','c','d','e','f','g','h', 'i', 'j', 'k', 'l']
>>> print list1[:5]
['a', 'b', 'c', 'd', 'e']
>>> print list1[-7:]
['f', 'g', 'h', 'i', 'j', 'k', 'l']

Note how you can slice either positively or negatively. When you use a negative number, it means we slice from right to left.

Upvotes: 26

Mark R. Wilkins
Mark R. Wilkins

Reputation: 1302

Note that you can use a variable in a slice:

l = ['a',' b',' c',' d',' e']
c_index = l.index("c")
l2 = l[:c_index]

This would put the first two entries of l in l2

Upvotes: 19

no1
no1

Reputation: 727

list1=['x','y','z','a','b','c','d','e','f','g']
find=raw_input("Enter string to be found")
l=list1.index(find)
list1a=[:l]
list1b=[l:]

Upvotes: 2

Jon Clements
Jon Clements

Reputation: 142156

If you already know the indices:

list1 = ['x','y','z','a','b','c','d','e','f','g']
indices = [(0, 4), (5, 9)]
print [list1[s:e+1] for s,e in indices]

Note that we're adding +1 to the end to make the range inclusive...

Upvotes: 10

no1
no1

Reputation: 727

list1a=list[:5]
list1b=list[5:]

Upvotes: 5

Related Questions