Split a List into Parts Based on a Set of Indexes in Python

Split a list into sublists based on a set of indexes in Python

Something along these lines:

mylist = ['a','b','c','d','e','f','g','h','i','j']
myindex = [1,4]

[mylist[s:e] for s, e in zip([0]+myindex, myindex+[None])]

Output

[['a'], ['b', 'c', 'd'], ['e', 'f', 'g', 'h', 'i', 'j']]

Split a list into parts based on a set of indexes in Python

This is the simplest and most pythonic solution I can think of:

def partition(alist, indices):
return [alist[i:j] for i, j in zip([0]+indices, indices+[None])]

if the inputs are very large, then the iterators solution should be more convenient:

from itertools import izip, chain
def partition(alist, indices):
pairs = izip(chain([0], indices), chain(indices, [None]))
return (alist[i:j] for i, j in pairs)

and of course, the very, very lazy guy solution (if you don't mind to get arrays instead of lists, but anyway you can always revert them to lists):

import numpy
partition = numpy.split

Split a list into sub-lists based on index ranges

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

How to divide list according to index position?

Just slicing the list would work:

coords = [48.92504247289378, 9.147973368734435, 29707, 48.92504291087322, 9.147998449546572, 29707, 48.9250463088055, 9.148013780873235, 29707, 48.92505484289239, 9.148021595289876, 29707, 48.925070689333246, 9.148024125370592, 29707]
lat = coords[::3]
lon = coords[1::3]
alt = coords[2::3]

Splitting list into multiple lists - depending on elements index

You could split the strings in a list comprehension and use zip:

list(zip(*[i.split(';') for i in combinedList]))

[('40% Football', '30% Basketball', '20% Baseball', '10% Rugby'),
('40% Football', '30% Basketball', '20% Base-Ball', '10% Le Rugby'),
('40% Fuball', '30% Basketball', '20% Baseball', '10% Rugby'),
('40% Futbol', '30% Baloncesto', '20% Béisbol', '10% Rugby'),
('40% Calcio', '30% Pallacanestro', '', '10% Rugby')]

Python: split list into indices based on consecutive identical values

Solution in Python 3 , If you are only using counter :

from collections import Counter
my_list =[11,11,11,11,12,12,15,15,15,15,15,15,20,20,20]
count = Counter(my_list)
div= list(count.keys()) # take only keys
div.sort()
l = []
num = 0
for i in div:
t = []
for j in range(count[i]): # loop number of times it occurs in the list
t.append(num)
num+=1
l.append(t)
print(l)

Output:

[[0, 1, 2, 3], [4, 5], [6, 7, 8, 9, 10, 11], [12, 13, 14]]

Alternate Solution using set:

my_list =[11,11,11,11,12,12,15,15,15,15,15,15,20,20,20] 
val = set(my_list) # filter only unique elements
ans = []
num = 0
for i in val:
temp = []
for j in range(my_list.count(i)): # loop till number of occurrence of each unique element
temp.append(num)
num+=1
ans.append(temp)
print(ans)

EDIT:
As per required changes made to get desired output as mention in comments by @Protoss Reed

my_list =[11,11,11,11,12,12,15,15,15,15,15,15,20,20,20] 
val = list(set(my_list)) # filter only unique elements
val.sort() # because set is not sorted by default
ans = []
index = 0
l2 = [54,21,12,45,78,41,235,7,10,4,1,1,897,5,79]
for i in val:
temp = []
for j in range(my_list.count(i)): # loop till number of occurrence of each unique element
temp.append(l2[index])
index+=1
ans.append(temp)
print(ans)

Output:

[[54, 21, 12, 45], [78, 41], [235, 7, 10, 4, 1, 1], [897, 5, 79]]

Here I have to convert set into list because set is not sorted and I think remaining is self explanatory.

Another Solution if input is not always Sorted (using OrderedDict):

from collections import OrderedDict
v = OrderedDict({})
my_list=[12,12,11,11,11,11,20,20,20,15,15,15,15,15,15]
l2 = [54,21,12,45,78,41,235,7,10,4,1,1,897,5,79]
for i in my_list: # maintain count in dict
if i in v:
v[i]+=1
else:
v[i]=1
ans =[]
index = 0
for key,values in v.items():
temp = []
for j in range(values):
temp.append(l2[index])
index+=1
ans.append(temp)
print(ans)

Output:

[[54, 21], [12, 45, 78, 41], [235, 7, 10], [4, 1, 1, 897, 5, 79]]

Here I use OrderedDict to maintain order of input sequence which is random(unpredictable) in case of set.

Although I prefer @Ami Tavory's solution which is more pythonic.

[Extra work: If anybody can convert this solution into list comprehension it will be awesome because i tried but can not convert it to list comprehension and if you succeed please post it in comments it will help me to understand]

Splitting a list into N parts of approximately equal length

This code is broken due to rounding errors. Do not use it!!!

assert len(chunkIt([1,2,3], 10)) == 10  # fails

Here's one that could work:

def chunkIt(seq, num):
avg = len(seq) / float(num)
out = []
last = 0.0

while last < len(seq):
out.append(seq[int(last):int(last + avg)])
last += avg

return out

Testing:

>>> chunkIt(range(10), 3)
[[0, 1, 2], [3, 4, 5], [6, 7, 8, 9]]
>>> chunkIt(range(11), 3)
[[0, 1, 2], [3, 4, 5, 6], [7, 8, 9, 10]]
>>> chunkIt(range(12), 3)
[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]

Split list into smaller lists (split in half)

A = [1,2,3,4,5,6]
B = A[:len(A)//2]
C = A[len(A)//2:]

If you want a function:

def split_list(a_list):
half = len(a_list)//2
return a_list[:half], a_list[half:]

A = [1,2,3,4,5,6]
B, C = split_list(A)

How split an element and replace both part in list with python

Assuming you're happy with creating a new list, one way to achieve that is to join the existing list together with spaces and then split on either a space or a ':

import re

mylist = [
'La', 'domestication', "d'un",
'animal', 'ou', "d'un", 'végétal,',
'necessite', "l'acquisition",
"d'une", 'ferme'
]

my_new_list = re.split(r" |(?<=')", ' '.join(mylist))

Output:

[
'La', 'domestication', "d'", 'un',
'animal', 'ou', "d'", 'un', 'végétal,',
'necessite', "l'", 'acquisition',
"d'", 'une', 'ferme'
]

Note this assumes the words in the list don't have a space in them; if they might, you can just replace the space in the code with a character (or character sequence) which does not occur in the words, e.g. \0:

my_new_list = re.split(r"\0|(?<=')", '\0'.join(mylist))

How to split a list based on a condition?

good = [x for x in mylist if x in goodvals]
bad = [x for x in mylist if x not in goodvals]

is there a more elegant way to do this?

That code is perfectly readable, and extremely clear!

# files looks like: [ ('file1.jpg', 33L, '.jpg'), ('file2.avi', 999L, '.avi'), ... ]
IMAGE_TYPES = ('.jpg','.jpeg','.gif','.bmp','.png')
images = [f for f in files if f[2].lower() in IMAGE_TYPES]
anims = [f for f in files if f[2].lower() not in IMAGE_TYPES]

Again, this is fine!

There might be slight performance improvements using sets, but it's a trivial difference, and I find the list comprehension far easier to read, and you don't have to worry about the order being messed up, duplicates being removed as so on.

In fact, I may go another step "backward", and just use a simple for loop:

images, anims = [], []

for f in files:
if f.lower() in IMAGE_TYPES:
images.append(f)
else:
anims.append(f)

The a list-comprehension or using set() is fine until you need to add some other check or another bit of logic - say you want to remove all 0-byte jpeg's, you just add something like..

if f[1] == 0:
continue


Related Topics



Leave a reply



Submit