Related
There are many similar questions on here, but I can't find exactly what I'm looking for.
I want to split a list into sublists, each of which is exactly length x. This can include overlap, and the area of overlap doesn't matter so much. For example:
list_to_split = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
max_len = 3
desired_result = [[1, 2, 3], [3, 4, 5], [6, 7, 8], [8, 9, 10]]
# or
max_length = 4
desired_result = [[1, 2, 3, 4], [4, 5, 6, 7], [7, 8, 9, 10]]
# or
max_len = 5
desired_result = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]
It doesn't matter how many final sublists there are, though I don't want any more than necessary.
It also doesn't matter where the overlap happens, I just need to capture all the individual items in the original list and have each sublist result in the same number of items.
Thanks!
You can adjust the accepted answer by NedBatchelder in this thread to work for the described scenario.
This is a generator function which I think is a pretty neat solution.
def chunks(lst, n):
"""Yield successive n-sized chunks from lst."""
# n must not be 0
for i in range(0, len(lst), n):
if i + n >= len(lst):
yield lst[-n:]
else:
yield lst[i:i + n]
l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
for i in range(1, 11):
print(list(chunks(l, i)))
Expected output:
[[1], [2], [3], [4], [5], [6], [7], [8], [9], [10]]
[[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [8, 9, 10]]
[[1, 2, 3, 4], [5, 6, 7, 8], [7, 8, 9, 10]]
[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]
[[1, 2, 3, 4, 5, 6], [5, 6, 7, 8, 9, 10]]
[[1, 2, 3, 4, 5, 6, 7], [4, 5, 6, 7, 8, 9, 10]]
[[1, 2, 3, 4, 5, 6, 7, 8], [3, 4, 5, 6, 7, 8, 9, 10]]
[[1, 2, 3, 4, 5, 6, 7, 8, 9], [2, 3, 4, 5, 6, 7, 8, 9, 10]]
[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]
The trick as I see it is to iterate an index in steps of x but "clip" the last one to be no less than x from the end:
>>> a = list(range(1, 11))
>>> x = 3
>>> [a[i:i+x] for i in (min(i, len(a) - x) for i in range(0, len(a), x))]
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [8, 9, 10]]
Taken straight from itertools' recipes:
from itertools import zip_longest
def grouper(iterable, n, *, incomplete='fill', fillvalue=None):
"Collect data into non-overlapping fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, fillvalue='x') --> ABC DEF Gxx
# grouper('ABCDEFG', 3, incomplete='strict') --> ABC DEF ValueError
# grouper('ABCDEFG', 3, incomplete='ignore') --> ABC DEF
args = [iter(iterable)] * n
if incomplete == 'fill':
return zip_longest(*args, fillvalue=fillvalue)
if incomplete == 'strict':
return zip(*args, strict=True)
if incomplete == 'ignore':
return zip(*args)
else:
raise ValueError('Expected fill, strict, or ignore')
You may then use the "fill" option, and add the last item continuously if you wish to guarantee the size of the sublist:
>>> list_to_split = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> max_len = 3
>>> list(grouper(list_to_split, max_len, fillvalue=list_to_split[-1]))
[(1, 2, 3), (4, 5, 6), (7, 8, 9), (10, 10, 10)]
Iterate over the list, slicing max_len elements at a time. We start the slice at min(idx, len(list_to_split) - max_len)) in case we're too close to the end of the list:
list_to_split = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
max_len = 3
result = []
for idx in range(0, len(list_to_split), max_len):
start = min(idx, len(list_to_split) - max_len)
result.append(list_to_split[start:start + max_len])
print(result)
You can turn this into a list comprehension, but it's admittedly not very readable:
list_to_split = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
max_len = 3
result = [
list_to_split[
min(idx, len(list_to_split) - max_len):
min(idx, len(list_to_split) - max_len) + max_len]
for idx in range(0, len(list_to_split), max_len)
]
print(result)
Both of these output:
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [8, 9, 10]]
Following code should do without any libraries, though there are many libraries too that you can use
def main():
'''The Main'''
l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
x = 3
print([l[i:i+x] for i in range(0, len(l), x)])
if __name__ == '__main__':
main()
Output
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
I'm trying to split a list into groups based on index pairs from another list, given:
>>> l = list(range(10))
>>> l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> idx = [0, 5]
I need to break up the list resulting in:
>>> l[0:5]
[0, 1, 2, 3, 4]
>>> l[5:]
[5, 6, 7, 8, 9]
The list idx will at a minimum always be [0], but may be of size n; values inside idx will always be sorted ascending.
Currently I have:
>>> l = list(range(10))
>>> idx = [0, 5]
>>> idx.append(None)
>>> [l[idx[i]:idx[i + 1]] for i in range(len(idx) - 1)]
[[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]
Is there a way to accomplish this without explicitly appending Non and iterating over a range?
Edit: for another example...
Given:
>>> l = list(range(14))
>>> l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
>>> idx = [0, 5, 10]
Desired result:
[[[0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [10, 11, 12, 13]]
You could try about itertools.zip_longest:
from itertools import zip_longest
l = list(range(14))
idx = [0, 5, 10]
print([l[pre: next] for pre, next in zip_longest(idx,idx[1:])])
Result:
[[0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [10, 11, 12, 13]]
With numpy you can use numpy.split()
import numpy as np
res =[list(x) for x in np.split(l, idx) if x.size != 0]
print(res)
Output:
[[0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [10, 11, 12, 13]]
result = [l[curr_idx:curr_idx+idx[1]] for curr_idx in idx]
result
[[0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [10, 11, 12, 13]]
Let's say I have a list or an array of the type:
mylist = [1, 2, 3, 4]
And I want to replace an item in this list. Normally I would use something like the following:
mylist[2] = 7
That works well. However, can someone explain how to create all possible permutations of mylist when replacing one or more items in mylist. For example, I want to create the following:
[7, 2, 3, 4]
[7, 7, 3, 4]
[7, 2, 7, 4]
[7, 7, 7, 4]
[7, 2, 3, 7]
...(and so on)
I know I can use itertools to generate all possible permutations, but how can I specify that I want to substitute an item in all possible locations in the list before generating the permutations? Here is how I tried to use itertools:
list(itertools.permutations([1,2,3,4,7], 4))
This doesn't work because it doesn't substitute 7 more than one time per permutation, and it also generates permutations that do not include the number 7.
Use itertools.combinations to find the indices to replace:
replace = 7
mylist = [1, 2, 3, 4]
for i in range(1, len(mylist) + 1):
for selected in itertools.combinations(range(len(mylist)), i):
res = mylist[:]
for n in selected:
res[n] = replace
print(res)
Output:
[7, 2, 3, 4]
[1, 7, 3, 4]
[1, 2, 7, 4]
[1, 2, 3, 7]
[7, 7, 3, 4]
[7, 2, 7, 4]
[7, 2, 3, 7]
[1, 7, 7, 4]
[1, 7, 3, 7]
[1, 2, 7, 7]
[7, 7, 7, 4]
[7, 7, 3, 7]
[7, 2, 7, 7]
[1, 7, 7, 7]
[7, 7, 7, 7]
You can create a function and just pass the list and value to that function and you get what you want :
import itertools
def replaced_it(list_1,value):
final_list = []
len_=len(list_1)
track_index = [k for k, j in enumerate(list_1)]
for i in range(len(track_index) + 1):
empty_list = [value]
replaced_one = list_1[:]
for ia in itertools.permutations(track_index, r=i):
if ia:
for i, j in zip(ia, empty_list * len(ia)):
replaced_one[i] = j
if replaced_one not in final_list:
final_list.append(replaced_one)
replaced_one = list_1[:]
return final_list
print(replaced_it([1,2,3,4],7))
output:
[[7, 2, 3, 4], [1, 7, 3, 4], [1, 2, 7, 4], [1, 2, 3, 7], [7, 7, 3, 4], [7, 2, 7, 4], [7, 2, 3, 7], [1, 7, 7, 4], [1, 7, 3, 7], [1, 2, 7, 7], [7, 7, 7, 4], [7, 7, 3, 7], [7, 2, 7, 7], [1, 7, 7, 7], [7, 7, 7, 7]]
I need to filter a list of character ie
In [16]: list
Out[16]: [[1, 2, 3, 4, 5, 6, 7, 8], [2, 3, 6, 3, 6, 2, 7], [4, 5, 9, 3, 1, 8]]
characters to grep is, g = [4,8]
In [27]: a = filter(lambda x:g in x, list)
In [28]: a
Out[28]: []
But I am ending up with this. Can someone help me?
I need the output as
[[1, 2, 3, 4, 5, 6, 7, 8], [4, 5, 9, 3, 1, 8]]
Your issue is that g in x is never True because g is a list that and that is never within one of your sub-lists, e.g. ([4,8] in [4,8,7] returns False). The right approach with filter:
l = [[1, 2, 3, 4, 5, 6, 7, 8], [2, 3, 6, 3, 6, 2, 7], [4, 5, 9, 3, 1, 8]]
g = [4,8]
filter(lambda x:all(c in x for c in g), l)
# [[1, 2, 3, 4, 5, 6, 7, 8], [4, 5, 9, 3, 1, 8]]
Or list comprehension:
[item for item in l if all(c in item for c in g)]
# [[1, 2, 3, 4, 5, 6, 7, 8], [4, 5, 9, 3, 1, 8]]
Note, don't name your variables list, this shadows the built-in name
I am working on the following problem:
This function returns a list of all possible sublists in L of length n without skipping elements in L. The sublists in the returned list should be ordered in the way they appear in L, with those sublists starting from a smaller index being at the front of the list.
Example 1, if L = [10, 4, 6, 8, 3, 4, 5, 7, 7, 2] and n = 4 then your function should return the list [[10, 4, 6, 8], [4, 6, 8, 3], [6, 8, 3, 4], [8, 3, 4, 5], [3, 4, 5, 7], [4, 5, 7, 7], [5, 7, 7, 2]]
My solution works but how can I make it shorter? What is a better way to do this?
def getSublists(L, n):
newN = n
myList = []
for i in range(len(L)):
orginalLen = L[i:n]
if(len(orginalLen) == n):
myList.append(L[i:n])
n = n + 1
else:
myList.append(L[i:n])
n = n + 1
if(newN == 1):
print(myList)
else:
print(myList[:len(myList)-(n-1)])
getSublists([10, 4, 6, 8, 3, 4, 5, 7, 7, 2],4)
getSublists([1], 1)
getSublists([0, 0, 0, 0, 0], 2)
OUTPUT
[[10, 4, 6, 8], [4, 6, 8, 3], [6, 8, 3, 4], [8, 3, 4, 5], [3, 4, 5, 7], [4, 5, 7, 7], [5, 7, 7, 2]]
[[1]]
[[0, 0], [0, 0], [0, 0], [0, 0]]
l = [1,2,3,4,5,6,87,9]
n = ..
print [l[i:i+n] for i in range(len(l)-n+1)]
maybe you need.
In one line:
get_sublists = lambda ls, n: [ls[x:x+n] for x in range(len(ls)-n+1)]
get_sublists([10, 4, 6, 8, 3, 4, 5, 7, 7, 2], 4)
[[10, 4, 6, 8], [4, 6, 8, 3], [6, 8, 3, 4], [8, 3, 4, 5], [3, 4, 5, 7], [4, 5, 7, 7], [5, 7, 7, 2]]
def get_sublists(L, n):
return [ L[i:i+n] for i in range(len(L)-n) ]
I completed the program a little better understanding of the reader.
def getSublists(L, n):
new_list = []
for i in range(len(L)-n+1):
a = L[i:i+n]
new_list.append(a)
return new_list
answer:
[[10, 4, 6, 8],
[4, 6, 8, 3],
[6, 8, 3, 4],
[8, 3, 4, 5],
[3, 4, 5, 7],
[4, 5, 7, 7],
[5, 7, 7, 2]]
This is pretty readable I think, to understand the concept. The idea here is to iterate through the numbers from 0 to the length of L, minus 4. And just take the sublist of L from your current index i, to i+4. Iterating to length-4 ensures you don't try to access an index out of bounds!
>>> for i in range(len(L)-4+1):
print L[i:i+4]
[10, 4, 6, 8]
[4, 6, 8, 3]
[6, 8, 3, 4]
[8, 3, 4, 5]
[3, 4, 5, 7]
[4, 5, 7, 7]
[5, 7, 7, 2]