def splitlist(L):
if not L: return []
answer = [[L[0]]]
for i in L[1:]:
if i - answer[-1][-1] < 4:
answer[-1].append(i)
else:
answer.append([i])
return answer
Output:
In [112]: splitlist([1,2,3,9,10,11,100,200])
Out[112]: [[1, 2, 3], [9, 10, 11], [100], [200]]
Answer from inspectorG4dget on Stack Overflowdef splitlist(L):
if not L: return []
answer = [[L[0]]]
for i in L[1:]:
if i - answer[-1][-1] < 4:
answer[-1].append(i)
else:
answer.append([i])
return answer
Output:
In [112]: splitlist([1,2,3,9,10,11,100,200])
Out[112]: [[1, 2, 3], [9, 10, 11], [100], [200]]
Short solution using numpy module:
import numpy as np
arr = np.array([1,2,3,9,10,11,100,200])
out = [a.tolist() for a in np.split(arr, np.where(np.diff(arr) > 4)[0]+1)]
print(out)
The output:
[[1, 2, 3], [9, 10, 11], [100], [200]]
np.where(np.diff(arr) > 4)- find the array indices where condition "difference between next value and previous value is greater than 4" is metnp.split(x, indices)- split the initial array by crucial indices
Use a dictionary for a variable number of variables.
In this case, you can use itertools.groupby to efficiently separate your lists:
L = ['abcd 1233','cdgfh3738','hryg21','**L**',
'gdyrhr657','abc31637','**R**','7473hrtfgf']
from itertools import groupby
# define separator keys
def split_condition(x):
return x in {'**L**', '**R**'}
# define groupby object
grouper = groupby(L, key=split_condition)
# convert to dictionary via enumerate
res = dict(enumerate((list(j) for i, j in grouper if not i), 1))
print(res)
{1: ['abcd 1233', 'cdgfh3738', 'hryg21'],
2: ['gdyrhr657', 'abc31637'],
3: ['7473hrtfgf']}
Consider using one of many helpful tools from a library, i.e. more_itertools.split_at:
Given
import more_itertools as mit
lst = [
"abcd 1233", "cdgfh3738", "hryg21", "**L**",
"gdyrhr657", "abc31637", "**R**",
"7473hrtfgf"
]
Code
result = list(mit.split_at(lst, pred=lambda x: set(x) & {"L", "R"}))
Demo
sublist_1, sublist_2, sublist_3 = result
sublist_1
# ['abcd 1233', 'cdgfh3738', 'hryg21']
sublist_2
# ['gdyrhr657', 'abc31637']
sublist_3
# ['7473hrtfgf']
Details
The more_itertools.split_at function splits an iterable at positions that meet a special condition. The conditional function (predicate) happens to be a lambda function, which is equivalent to and substitutable with the following regular function:
def pred(x):
a = set(x)
b = {"L", "R"}
return a.intersection(b)
Whenever characters of string x intersect with L or R, the predicate returns True, and the split occurs at that position.
Install this package at the commandline via > pip install more_itertools.
I've quickly written one way to do this, I'm sure there are more efficient ways, but this works at least:
num_list =[97, 122, 99, 98, 111, 112, 113, 100, 102]
arrays = [[num_list[0]]] # array of sub-arrays (starts with first value)
for i in range(1, len(num_list)): # go through each element after the first
if num_list[i - 1] < num_list[i]: # If it's larger than the previous
arrays[len(arrays) - 1].append(num_list[i]) # Add it to the last sub-array
else: # otherwise
arrays.append([num_list[i]]) # Make a new sub-array
print(arrays)
Hopefully this helps you a bit :)
Here is a one-linear Numpythonic approach:
np.split(arr, np.where(np.diff(arr) < 0)[0] + 1)
Or a similar approach to numpy code but less efficient:
from operator import sub
from itertools import starmap
indices = [0] + [
i+1 for i, j in enumerate(list(
starmap(sub, zip(num_list[1:], num_list)))
) if j < 0] + [len(num_list)
] + [len(num_list)]
result = [num_list[i:j] for i, j in zip(indices, indices[1:])]
Demo:
# Numpy
In [8]: np.split(num_list, np.where(np.diff(num_list) < 0)[0] + 1)
Out[8]:
[array([ 97, 122]),
array([99]),
array([ 98, 111, 112, 113]),
array([100, 102])]
# Python
In [42]: from operator import sub
In [43]: from itertools import starmap
In [44]: indices = [0] + [i+1 for i, j in enumerate(list(starmap(sub, zip(num_list[1:], num_list)))) if j < 0] + [len(num_list)]
In [45]: [num_list[i:j] for i, j in zip(indices, indices[1:])]
Out[45]: [[97, 122], [99], [98, 111, 112, 113], [100, 102]]
Explanation:
Using np.diff() you can get the differences of each item with their next item (up until the last element). Then you can use the vectorized nature of numpy to get the indices of the places where this difference is negative, which can be done with a simple comparison and np.where(). Finally you can simply pass the indices to np.split() to split the array based on those indices.
try this,
my_list = ['pdf', 'csv', 'csv','csv','txt','txt','txt','txt','pdf','pdf','csv','txt','txt','pdf', 'csv', 'csv','pdf','csv','txt','txt' ]
counter = [0,0,0]
counter[0]=my_list.count('pdf')
counter[1]=my_list.count('csv')
counter[2]=my_list.count('txt')
l2=[]
lists = []
pdf,csv,txt=counter
for i in range(max(counter)):
l2=[]
if pdf>=0:
l2.append('pdf')
pdf-=1
if csv>=0:
l2.append('csv')
csv-=1
if txt>=0:
l2.append('txt')
txt-=1
lists.append(l2)
print(lists)
output:
[['pdf', 'csv', 'txt'], ['pdf', 'csv', 'txt'], ['pdf', 'csv', 'txt'], ['pdf', 'csv', 'txt'], ['pdf', 'csv', 'txt'], ['pdf', 'csv', 'txt'], ['csv', 'txt'], ['csv', 'txt']]
hope this helps you!
You can use a simple dictionary for counting.
myDict = dict()
for s in my_list:
if s in myDict:
myDict[s] += 1
else:
myDict[s] = 1
lists = [['pdf', 'csv', 'txt'] for i in range(min(myDict.values()))]
The above code counts the number of occurance of each element in my_list and creates another list of list. You might need a little modification to get the output you want since it is not clear what exactly should the output be
You could collections.defaultdict here for mapping.
from collections import defaultdict
d = defaultdict(list)
for l in listOfObjects:
d[l.someAttribute].append(l)
out = d.values()
l1 , l2, l3 = d['l1'], d['l2'], d['l3']
d would be of the form.
{
attr1 : [...],
attr2 : [...],
...
attrn : [...]
} That similar question's answer is amazing. I haven't thought about that for splitting... Anyway, you can do something similar but it would be less readable:
for l in listOfObjects:
(l3, l2, l1)[(l.someAttribute == "l1")*2 or l.someAttribute == "l2"].append(l)
This will work for any boolean conditions. or returns first truthy value (or False). True==1, so we add *2 for the index that we want to be equal to 2.
But as I said, it's not really readable. And not scalable.
As for speed: or is short-circuiting, returns first truthy value, so the check of conditions should be similar to your approach. You might want to keep the lookup tuple defined outside of the loop.
And more readable thing using dict because your conditions are based on equality (note: attribute you want also has to be hashable)
lookup = {"l1": l1, "l2": l2}
for l in listOfObjects:
lookup.get(l.someAttribute, l3).append(l)
dict.get gets default value as second - so it's perfect for our else catchall.
In terms of speed: Dictionary lookup will have only one check, as opposed to a chain of or conditions of chain of ifs
input = ['1', '2','#','3','4','#','5']
s = ''.join(input).split('#')
r = []
for i in s:
r.append(list(i))
output = r
Use string join and split method:
alist= ['1', '2','#','3','4','#','5']
as_string = ' '.join(alist).split('#')
as_string_list = [i.strip().split(' ') for i in as_string]
print as_string_list