Split list into smaller lists based on values? - python

Say I have a list: [1, 2, 3, 4, -1, 5, 6, 7, -1, 0, 0, 3, 2, 1]
I want to split this list into using values -1 or 0, 0 as a delimiter:
[[1, 2, 3, 4], [5, 6, 7], [], [3, 2, 1]]
(Note the empty 3rd list)
How would I achieve this? My current solution is just a trivial loop but I'm wondering if theres a more pythonic solution (using list comprehensions) for delimiters of any length?
Current solution as requested (messy and hacky :P)
string = '|'.join([str(x) for x in data]).replace('-1', ',').replace('0|0', ',')
buckets = [x.split('|') if y for x in string.split(',')]

It's not trivial, but you can done it like this:
my_list = [1, 2, 3, 4, -1, 5, 6, 7, -1, 0, 0, 3, 2, 1]
my_list = ','.join(map(str, my_list))
my_list = [x.split(',') for y in my_list.split('0,0,') for x in y.split(',-1,')]
my_list = [map(int, x) if x != [''] else [] for x in my_list]

Using simple for loop and check conditions
Code:
lst = [1, 2, 3, 4, -1, 5, 6, 7, -1, 0, 0, 3, 2, 1,-1,0]
output_lst = []
check = 0
sample=[]
for val in lst:
if val == -1 :
output_lst.append(sample)
check = 0
sample = []
continue
if val == 0 :
if check ==1 :
output_lst.append(sample[:-1])
check = 0
sample = []
continue
check = 1
sample.append(val)
if check ==1:
output_lst.append(sample)
print output_lst
Output:
[[1, 2, 3, 4], [5, 6, 7], [], [3, 2, 1], [0]]

Try this
use one iteration for to do it.
ar = [1, 2, 3, 4, -1, 5, 6, 7, -1, 0, 0, 3, 2, 1]
data = ', '.join(map(str, ar))
import re
data = re.split(", -1,| 0, 0,",data)
bucket = []
import ast
for y in data:
hac = ast.literal_eval("["+y+"]")
bucket.append(hac)
print bucket

Related

Replacing items in a list with items from another list in python

list1 = [3,4,1,1,0,3,1,0,4,3,3,2,3]
list2 = [0,2,1,0,5]
Would it be possible to replace each 3 in list1 with an element from list2? If so, how would I go about doing this?
You could create an iterator for list2, and then call next() to replace the next element in list1 that is equal to 3, while using a list comprehension.
list1 = [3,4,1,1,0,3,1,0,4,3,3,2,3]
list2 = [0,2,1,0,5]
l2 = iter(list2)
out = [i if i!=3 else next(l2) for i in list1]
print(out)
Output:
[0, 4, 1, 1, 0, 2, 1, 0, 4, 1, 0, 2, 5]
We can use two pointers to keep track of list1 and list2. Then we replace each 3 in list1 with a value from list2 even it is not 0 until traversing to the end of any of the list.
list1 = [3, 4, 1, 1, 0, 3, 1, 0, 4, 3, 3, 2, 3]
list2 = [0, 0, 0, 0, 0]
x = 0
y = 0
while x < len(list1) and y < len(list2):
if list1[x] == 3:
list1[x] = list2[y]
y += 1
x += 1
print(list1)
Output:
[0, 4, 1, 1, 0, 0, 1, 0, 4, 0, 0, 2, 0]
list1 = [3,4,1,1,0,3,1,0,4,3,3,2,3]
list2 = [0,2,1,0,5]
l1_num = 3 # number to be replaced in list 1
l2_num = 0 # number to be replaced in list 2
n = min(list1.count(l1_num),list2.count(l2_num))
for i in range(n):
list1[list1.index(l1_num)] = l2_num
list2[list2.index(l2_num)] = l1_num
#list1 = [0, 4, 1, 1, 0, 0, 1, 0, 4, 3, 3, 2, 3]
#list2 = [3, 2, 1, 3, 5]
we can use for in and store our needed short list value out of the loop. like the following code will replace all 3 in list1 with zeros and all 0 in list2 with 3s in list1:
list1 = [3,4,1,1,0,3,1,0,4,3,3,2,3]
list2 = [0,1,0,3,0]
#shortlistval will be used to store short list desired value
shortlistVal =1;#default val is just for declaration
for i1 in range(0, len(list1)):
for i in range(0,len(list2)):
if list1[i1] ==3 and list2[i] == 0:
shortlistVal=list2[i]
list2[i]=list1[i1]
if list1[i1]==3:
list1[i1]= shortlistVal
print(list1)
print(list2)
Output:
[0, 4, 1, 1, 0, 0, 1, 0, 4, 0, 0, 2, 0]
[3, 1, 3, 3, 3]
Use two for loops and replace each 3 for 0 s in list 2.
list1 = [3,4,1,1,0,3,1,0,4,3,3,2,3]
list2 = [0,2,1,0,5]
for i in range(list2.count(0)):
for x in list1:
if x == 3: list1[list1.index(x)] = 0; break
print(list1)
output:
[0, 4, 1, 1, 0, 0, 1, 0, 4, 3, 3, 2, 3]

split list based on the variable values in different list

I have two lists:
List1=[2,4,3]
List2=[1,2,1,3,2,1,5,4,1]
Need to generate output like this:
ResultList=[[1,2],[1,3,2,1],[5,4,1]]
Need help!!!
The below should work
list1 = [2,4,3]
list2 = [1,2,1,3,2,1,5,4,1]
offset = 0
data = []
for x in list1:
data.append(list2[offset:offset+x])
offset += x
print(data)
output
[[1, 2], [1, 3, 2, 1], [5, 4, 1]]
You can try this -
result_list=[]
a = 0
for i in list1:
result_list.append(list2[a:a+i])
a += i
from itertools import islice
lengths = [2, 4, 3]
numbers = iter([1, 2, 1, 3, 2, 1, 5, 4, 1])
lists = [list(islice(numbers, length)) for length in lengths]
print(lists)
Output:
[[1, 2], [1, 3, 2, 1], [5, 4, 1]]
>>>

How to fill array from index to another index in Python

How to fill an array from on index let's say 3 to 5 in an array containing 10 element without a for loop?
Input:
[0,5,8,4,6,7,5,1,3,0]
Output:
[0,5,8,'replaced','replaced','replaced',5,1,3,0]
Since lists are mutable, you can just use list slicing:
>>> lst = [0,5,8,4,6,7,5,1,3,0]
>>> lst[3:6] = ['','','']
>>> lst
[0, 5, 8, '', '', '', 5, 1, 3, 0]
One way:
arr = [0,5,8,4,6,7,5,1,3,0]
arr[3:6] = ['replaced']*(6-3)
# [0, 5, 8, 'replaced', 'replaced', 'replaced', 5, 1, 3, 0]
Here's another way to do it
>>> nums = [0,5,8,4,6,7,5,1,3,0]
>>> ['replaced' if 3 <= i <= 5 else num for i, num in enumerate(nums)]
[0, 5, 8, 'replaced', 'replaced', 'replaced', 5, 1, 3, 0]

how to find the count the difference back to the previous zero in a list?

I have below list
[7, 2, 0, 3, 4, 2, 5, 0, 3, 4]
and the result list is
[1, 2, 0, 1, 2, 3, 4, 0, 1, 2]
the result obtained by with the below logic
For each value, count the difference back to the previous zero (or the start of the Series,
whichever is closer).
am trying to implement , but not able to get .
So how to find the previous zero position , such that we can get that series ?
I tried below , but somehow it is failing , and it is seems not good solution
import pandas as pd
df = pd.DataFrame({'X': [7, 2, 0, 3, 4, 2, 5, 0, 3, 4]})
#print(df)
df_series = df['X']
print(df_series.iloc[-1])
target_series = pd.Series([])
#print(target_series)
def calculate_value(i,actual_index):
if(df_series.iloc[i-1] == 0):
if(i < 0):
zero_position = i + df_series.size-1
if(actual_index - 0 < zero_position):
target_series[actual_index]=actual_index+1
return
else:
target_series[actual_index]=zero_position
return
else:
target_series[actual_index]=target_series[actual_index]+1
return
else:
if(i+df_series.size != actual_index):
calculate_value(i-1,actual_index)
for i in df.index:
if(df_series[i]==0 and i!=0):
target_series[i]=0
elif(df_series[i]!=0 and i==0):
target_series[i]=1
else:
calculate_value(i,i)
print(target_series)
If you want a Pandas one-liner solution:
import pandas as pd
s = pd.Series([7, 2, 0, 3, 4, 2, 5, 0, 3, 4])
(s.groupby(s.eq(0).cumsum().mask(s.eq(0))).cumcount() + 1).mask(s.eq(0), 0).tolist()
Output:
[1, 2, 0, 1, 2, 3, 4, 0, 1, 2]
If you stick to the list you can get your result quite easily:
l = [7, 2, 0, 3, 4, 2, 5, 0, 3, 4]
i = 0
r = []
for element in l:
if element != 0:
i += 1
else:
i = 0
r.append(i)
r
#[1, 2, 0, 1, 2, 3, 4, 0, 1, 2]
Here is a working solution for you:
a = [7, 2, 0, 3, 4, 2, 5, 0, 3, 4]
b = []
z_pos = -1
for i, n in enumerate(a):
if n == 0:
z_pos = i
b.append(i - z_pos)
print(b) # [1, 2, 0, 1, 2, 3, 4, 0, 1, 2]
It does not use anything too fancy so I explaining its internal workings is unnecessary I think. If however there is something that is not clear to you let me know.
If you want to use python only, here is the solution:
a = [7, 2, 0, 3, 4, 2, 5, 0, 3, 4]
z = None
b = []
for i in range(len(a)):
if a[i] != 0 and z== None:
b.append(i+1)
elif a[i] == 0:
b.append(0)
z = 0
else:
z += 1
b.append(z)
b is the required list.
Here is how to do it with a standard list, not Pandas dataframe, but the logic is the same
arr = [7,2,0,3,4,5,1,0,2]
arr2 = []
counter = 1
for item in arr:
if(item==0):
counter = 0
arr2.append(counter)
counter+=1
print(arr2)
You can see the code working here.
Some explanations:
What you want is a sort of counter between two 0 in your array.
So you loop over your array, and each time you encounter a 0 you reset your counter, and you insert the value of your counter each iteration of the loop.
If you are a fan of shortness instead of readability or effectiveness, you can also roll with this:
a = [7, 2, 0, 3, 4, 2, 5, 0, 3, 4]
distances = [([0]+a)[:idx][::-1].index(0) for idx in range(1, len(a)+2)][1:]
Which gives the desired result:
print(distances)
>> [1, 2, 0, 1, 2, 3, 4, 0, 1, 2]
Solution with no for loops or apply, just some pandas groupby fun.
We use
df = pd.DataFrame({'X': [7, 2, 0, 3, 4, 2, 5, 0, 3, 4]})
# make a new column with zeros at zeros and nans elsewhere
df = df.assign(idx_from_0=df.loc[df.X==0])
nul = df['idx_from_0'].isnull()
df.assign(idx_from_0=nul.groupby((nul.diff() == 1).cumsum()).cumsum())
Out[1]:
X idx_from_0
0 7 1.0
1 2 2.0
2 0 0.0
3 3 1.0
4 4 2.0
5 2 3.0
6 5 4.0
7 0 0.0
8 3 1.0
9 4 2.0
The cumsum forward fill add one was taken from this answer.

How to change numbers around in a list (python)

i have been working on this for 3 hours now but i have no clue how to do it
can anyone help me with this?
values = [1, 2, 3, 4, 5]
temp = values[0]
for index in range (len(values) -1):
values[index] = values [index]
values[len(values)-1] = temp
print values
i want the printed values to be in order as [2,3,4,5,1]
by simply changing those in the brackets
deque is more efficient way to do
In [1]: import collections
In [3]: dq = collections.deque([1,2,3,4,5])
In [4]: dq.rotate(-1)
In [5]: dq
Out[5]: deque([2, 3, 4, 5, 1])
What you are trying to achieve is not available in the python libraries but you can leverage slicing to rotate list
Implementation
def rotate(seq, n = 1, direc = 'l'):
if direc.lower() == 'l':
seq = seq[n:] + seq[0:n]
else:
seq = seq[-n:] + seq[:-n]
return seq
Demonstration
>>> rotate(values)
[2, 3, 4, 5, 1]
>>> rotate(values,2,'l')
[3, 4, 5, 1, 2]
>>> rotate(values,2,'r')
[4, 5, 1, 2, 3]
Simple but powerful slice syntax:
values = [1, 2, 3, 4, 5]
shifted = values[1:]+values[:1]
assert shifted == [2, 3, 4, 5, 1]
How about time one-liner, in the spirit of sleepsort:
while values != [2, 3, 4, 5, 1]: random.shuffle(values)

Categories

Resources