Split a list into sub-lists based on index ranges
Question:
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]
Answers:
list1a=list[:5]
list1b=list[5:]
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.
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:]
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…
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
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)]
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]
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']]
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.
It’s better to use SequenceT instead of Sequence ’cause then 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 TypeVar
SequenceT = TypeVar('SequenceT', bound=Sequence)
def slice_in_2(seq: SequenceT, index: int) -> tuple[SequenceT, SequenceT]:
return seq[:index], seq[index:]
def slice_in_N(seq: SequenceT, indexes: Sequence[int]) -> list[SequenceT]:
previous_i = 0
seq2 = result = []
for i in indexes:
seq2 = slice_in_2(seq, i-previous_i)
result.append(seq2[0])
seq = seq2[1]
previous_i = i
result.append(seq2[1])
return result
t = (1, 2, 3, 4, 5)
print(slice_in_2(t, 3)) # Output: ((1, 2, 3), (4, 5))
print(slice_in_N(t, (2,3))) # Output: [(1, 2), (3,), (4, 5)]
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]
list1a=list[:5]
list1b=list[5:]
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.
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:]
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…
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
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)]
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]
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']]
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.
It’s better to use SequenceT instead of Sequence ’cause then 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 TypeVar
SequenceT = TypeVar('SequenceT', bound=Sequence)
def slice_in_2(seq: SequenceT, index: int) -> tuple[SequenceT, SequenceT]:
return seq[:index], seq[index:]
def slice_in_N(seq: SequenceT, indexes: Sequence[int]) -> list[SequenceT]:
previous_i = 0
seq2 = result = []
for i in indexes:
seq2 = slice_in_2(seq, i-previous_i)
result.append(seq2[0])
seq = seq2[1]
previous_i = i
result.append(seq2[1])
return result
t = (1, 2, 3, 4, 5)
print(slice_in_2(t, 3)) # Output: ((1, 2, 3), (4, 5))
print(slice_in_N(t, (2,3))) # Output: [(1, 2), (3,), (4, 5)]