Related
The input is always strictly increasing. I could write this with a for loop and lots of if-else conditions, but is there some simple way? Here is an example:
input: [2,3,4,6,8,9]
output: [[0,1,2],[4,5]]
input: [1,2,3,4]
output: [[0,1,2,3]]
input: [0,1,2,4,6,7,8,10,12,13,14]
output: [[0,1,2], [4,5,6], [8,9,10]]
For example here is the code I wrote
def get_mergable_indices(sent_order):
mergable_indices = []
continuous_sents = [0]
for index, value in enumerate(sent_order):
if index == 0:
continue
else:
if value - sent_order[index-1] == 1:
continuous_sents.append(index)
else:
if len(continuous_sents)>1:
mergable_indices.append(continuous_sents)
continuous_sents = [index]
if len(continuous_sents)>1:
mergable_indices.append(continuous_sents)
return mergable_indices
It's too big want to reduce it
Maybe you can try this:
def get_mergable_indices(sent_order):
lst, res = [j-i for i, j in enumerate(sent_order)], []
ci = 0
for i in set(lst):
lci = lst.count(i)
if lci > 1:
res.append(list(range(ci, lci + ci)))
ci += lci
return res
output:
>>> get_mergable_indices([2,3,4,6,8,9])
[[0, 1, 2], [4, 5]]
>>> get_mergable_indices([1,2,3,4])
[[0, 1, 2, 3]]
>>> get_mergable_indices([0,1,2,4,6,7,8,10,12,13,14])
[[0, 1, 2], [4, 5, 6], [8, 9, 10]]
This can easily be done without using any module.
def get_mergable_indices(sent_order):
lst = sent_order
out = []
l = []
for a in range(max(lst)): # set range to the max number in the list.
try:
if lst[a]+1 == lst[a+1]: # check current number plus 1 is equal to next number
l.append(a)
l.append(a+1)
else: # if not equal then append l to the out list also set the l to an empty list.
if l:
out.append(list(set(l)))
l = []
except IndexError:
pass
out.append(list(set(l)))
return (out)
output
input: [2,3,4,6,8,9]
output: [[0,1,2],[4,5]]
input: [1,2,3,4]
output: [[0,1,2,3]]
input: [0,1,2,4,6,7,8,10,12,13,14]
output: [[0,1,2], [4,5,6], [8,9,10]]
This can accept any iterable sequence:
from itertools import pairwise
def get_mergable_indices(sent_order):
result = []
curr = []
for idx, (i, j) in enumerate(pairwise(sent_order)):
if j - i == 1:
curr.append(idx)
elif curr:
curr.append(idx)
result.append(curr)
curr = []
if curr:
curr.append(idx + 1)
result.append(curr)
return result
Output:
>>> get_mergable_indices([2, 3, 4, 6, 8, 9])
[[0, 1, 2], [4, 5]]
>>> get_mergable_indices(range(1, 5))
[[0, 1, 2, 3]]
>>> get_mergable_indices([0, 1, 2, 4, 6, 7, 8, 10, 12, 13, 14])
[[0, 1, 2], [4, 5, 6], [8, 9, 10]]
This is my approach:
def check_continuous(inp_list):
idx = idy = 0
res = [[]]
while idx < len(inp_list) - 1:
# Not append repeated indices
if inp_list[idx] - inp_list[idx+1] == -1: # If the next element is 1 higher, just check for -1
if idx not in res[idy]:
res[idy].append(idx)
if idx+1 not in res[idy]:
res[idy].append(idx+1)
else:
# Don't append empty lists
if res[idy]:
res.append([])
idy += 1
idx += 1
return res
print(check_continuous([2,3,4,6,8,9]))
# [[0, 1, 2], [4, 5]]
print(check_continuous([1,2,3,4]))
# [[0, 1, 2, 3]]
print(check_continuous([0,1,2,4,6,7,8,10,12,13,14]))
# [[0, 1, 2], [4, 5, 6], [8, 9, 10]]
I think this could be highly improved
As I have mentioned in the comments, np.diff can be a good choice in this regard. The accepted answer used two loops again, but is written in smaller form, and is not so different than other answers. The problem can be solved by Just NumPy as:
a = np.array([0, 1, 2, 4, 6, 7, 8, 10, 12, 13, 14])
diff = np.diff(a, prepend=a[0]-2) # [2 1 1 2 2 1 1 2 2 1 1]
diff_w = np.where(diff == 1)[0] # [ 1 2 5 6 9 10]
mask_ = np.diff(diff_w, prepend=diff_w[0]-2) # [2 1 3 1 3 1]
mask_ = mask_ != 1 # [ True False True False True False]
con_values = np.insert(diff_w, np.where(mask_)[0], diff_w[mask_] - 1) # [ 0 1 2 4 5 6 8 9 10]
# result = np.split(con_values, np.where(np.diff(con_values, prepend=con_values[0] - 1) != 1)[0])
result = np.split(con_values, np.where(np.diff(con_values, prepend=con_values[0] - 2) != 1)[0])[1:]
# [array([0, 1, 2], dtype=int64), array([4, 5, 6], dtype=int64), array([ 8, 9, 10], dtype=int64)]
I have tested this code on your examples and some others and it works. But, if there be any problem using other samples, it can be handled with some little changes by inspiration from this code. I wrote this code in separate parts to be understandable more. You can combine them in just one line if it is important for you.
I want to create a multi dimensional Array out of normal array. When there is a 0 in my start array i want to change the row number by 1.
My start array looks like this:
arr = [1, 2, 3, 0, 4, 5, 6, 0, 7, 8, 9]
My futre multi array should look like this:
multi_arr = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
My code looks like this so far:
multi_arr = []
end = len(arr)
i = 0 #row
j = 0 #column
for h in range(end):
if arr[h] != 0:
j += 1
multi_arr[i][j]= arr[h]
elif arr[i] != 0:
i += 1
I always get a list index error with this code.
If you really want to work with lists, you dont need a column indexer. You can simply append the value to the correct list.
multi_arr = [[]] # start with a nested list, since your vector doesnt start with a 0
endi = len(arr)
i = 0 #row
for h in range(endi):
if arr[h] != 0:
multi_arr[i].append(arr[h])
else:
i += 1
multi_arr.insert(i,[]) # open new list
output:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
This should do the job in a simpler way:
arr = [1, 2, 3, 0, 4, 5, 6, 0, 7, 8, 9]
multi_arr = []
temp_arr = []
for h in arr:
if h != 0:
temp_arr.append(h)
else:
multi_arr.append(temp_arr)
temp_arr = []
if h != 0: # Insert the last array it the last number wasn't 0
multi_arr.append(temp_arr)
print(multi_arr)
This is happening because at the point where you are trying set multi_arr[i][j], it is still a 1-d array. You can verify this with a print statement or a debugger - like so:
for h in range(end):
if arr[h] != 0:
print(multi_arr)
j += 1
multi_arr[i][j]= arr[h]
elif arr[i] != 0:
i += 1
I would definitely try something more pythonic for what you are trying to accomplish, reading the elements into a temp array and appending that temp array to multi array.
arr = [1, 2, 3, 0, 4, 5, 6, 0, 7, 8, 9]
multi_arr = []
temp_array = []
for item in arr:
if item == 0:
multi_arr.append(temp_array)
temp_array = []
else:
temp_array.append(item)
multi_arr.append(temp_array)
print(multi_arr)
You are declaring a 1D array and appending like 2D array
One solution two your Problem is :
arr=[1,2,3,4,5,6,7,8,9]
multi_arr=[]
end = len(arr)
a = []
counter =0
for i in arr :
if counter < 3 :
a.append(i)
counter += 1
else:
multi_arr.append(a)
a=[]
counter = 0
a.append(i)
counter += 1
multi_arr.append(a)
print(multi_arr)
Here is a yield approach:
def f(arr):
res = []
for x in arr:
if x == 0:
yield res
res = []
else:
res.append(x)
yield res
list(f(arr))
#> [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
A different approach for you: super simple and no loop.
import numpy as np
arr = [1, 2, 3, 0, 4, 5, 6, 0, 7, 8, 9]
a = [i for i in arr if i]
x = arr[arr!=0] + 1
np.array(a).reshape([-1, x])
Output:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
And if you need lists, just use np.array(a).reshape([x, y]).tolist() instead.
One-liner:
After converting your list to a numpy array a = np.array(arr):
a[a!=0].reshape([-1, len(a) - np.count_nonzero(a)+1])
This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 2 years ago.
I was trying to do following operation on a list 2 times:
-> for each index i: arr[i] = d - arr[i] where d is maximum element in list
-> append the resultant list to another list
My code:
arr = [5, -1, 4, 2, 0]
n = len(arr)
res = []
for _ in range(2):
d = max(arr)
for i in range(n):
arr[i] = d-arr[i]
res.append(arr)
print(res)
Output:
[[6, 0, 5, 3, 1], [6, 0, 5, 3, 1]]
Expected Output:
[[0, 6, 1, 3, 5], [6, 0, 5, 3, 1]]
Please help!
I would like to use a small function
arr = [5, -1, 4, 2, 0]
def fn(arr):
s = max(arr)
return [s - i for i in arr]
my_final_list = []
for i in range(2):
arr = fn(arr)
my_final_list.append(arr)
print(my_final_list)
[[0, 6, 1, 3, 5], [6, 0, 5, 3, 1]]
You put arr in the list res but keep modifying its values in the second loop. Make a new sub-list with values directly, otherwise your changes are reflected on all elements of res which are all identically pointing to arr.
# Using your conventions.
arr = [5, -1, 4, 2, 0]
res = []
for _ in range(2):
d = max(arr)
res.append([])
for i in range(len(arr)):
arr[i] = d-arr[i]
res[-1].append(arr[i])
print(res)
# >>> [[0, 6, 1, 3, 5], [6, 0, 5, 3, 1]]
Note that your variables names are hard to understand so here is a variant:
array = [5, -1, 4, 2, 0]
results = []
for _ in range(2):
array_max = max(array)
results.append([])
for i in range(len(array)):
array[i] = array_max - array[i]
results[-1].append(array[i])
print(results)
I want to take a list like:
x = [1,2,2,3,4,6,6]
and return a 2d list with the indexes of the repeating values:
[ [1,2], [5,6]]
I've tried the following:
new_list = []
i = 0
while i < len(x)-1:
if x[i] == x[i+1]:
new_list.append([x[i],x[i+1]]
i += 1
x is not necessarily sorted but has at least one series of repeating values. For example x can also be:
x = [1,4,2,3,3,3,7,0]
You can use itertools.groupby here.
from itertools import groupby
x=[1, 2, 2, 2, 3, 3, 4, 4, 6, 6, 6, 6, 6, 6, 8]
ranges=[list(g) for _,g in groupby(range(len(x)),lambda idx:x[idx])]
# [[0], [1, 2, 3], [4, 5], [6, 7], [8, 9, 10, 11, 12, 13], [14]]
# 1 2 2 2 3 3 4 4 6 6 6 6 6 6 8
final=[[r[0],r[-1]] for r in ranges if len(r)>1]
# [[1, 3], [4, 5], [6, 7], [8, 13]]
Pure Python approach:
x=[1, 2, 2, 2, 3, 3, 4, 4, 6, 6, 6, 6, 6, 6, 8]
out=[]
count=0
for i in range(1,len(x)):
prev=x[i-1]
if x[i]==prev:
count+=1
elif count and x[i]!=prev:
out.append([i-count-1,i-1])
count=0
if count:
out.append([i-count,i])
out
# [[1, 3], [4, 5], [6, 7], [8, 13]]
You can keep track of the current index and when the next element is equal to the value of the value in current_index, you append it to the result, but you need to increase the value of index until it's value will be different
x = [1, 2, 2, 3, 4, 6, 6]
result = []
cur_idx = 0
i = 1
while i < len(x):
if x[cur_idx] == x[i]:
result.append([cur_idx, x[cur_idx]])
# Increase value of i up to the index where there is different value
while i < len(x):
if x[cur_idx] != x[i]:
# Set cur_idx to the index of different value
cur_idx = i
i += 1
break
i += 1
else:
cur_idx = i
i += 1
print(result)
# [[1, 3], [5, 3]]
Try this code:
# Hello World program in Python
x = [1,2,2,3,4,6,6]
new_list = []
i = 0
indexes = []
while i < len(x)-1:
if x[i] == x[i+1]:
indexes.append(i)
indexes.append(i+1)
else:
indexes = list(set(indexes))
if len(indexes) != 0:
new_list.append(indexes)
indexes = []
i+=1
indexes = list(set(indexes))
if len(indexes) != 0:
new_list.append(indexes)
print(new_list)
Result:
[[1, 2], [5, 6]]
Try this.
def repeating_values( initital_list):
cache = {}
result = []
for i, element in enumerate(initital_list):
if element in cache:
result.append([cache[initital_list[i]], i])
else:
cache[element] = i
return result
For your input
x = [1,2,2,3,4,6,6]
print(repeating_values(x))
Result
[[1, 2], [5, 6]]
I want to split any matrix (most likely will be a 3x4) into two. One part will be the left hand and then the right hand - only the last column.
[[1,0,0,4], [[1,0,0], [4,
[1,0,0,2], ---> A= [1,0,0], B = 2,
[4,3,1,6]] [4,3,1]] 6]
Is there a way to do this in python and assign then as A and B?
Thank you!
Yes, you could do like this:
def split_last_col(mat):
"""returns a tuple of two matrices corresponding
to the Left and Right parts"""
A = [line[:-1] for line in mat]
B = [line[-1] for line in mat]
return A, B
split_last_col([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
output:
([[1, 2], [4, 5], [7, 8]], [3, 6, 9])
You could create A and B manually, like this:
def split(matrix):
a = list()
b = list()
for row in matrix:
row_length = len(row)
a_row = list()
for index, col in enumerate(row):
if index == row_length - 1:
b.append(col)
else:
a_row.append(col)
a.append(a_row)
return a, b
Or using lists comprehension:
def split(matrix):
a = [row[:len(row) - 1] for row in matrix]
b = [row[len(row) - 1] for row in matrix]
return a, b
Example:
matrix = [
[1, 0, 0, 4],
[1, 0, 0, 2],
[4, 3, 1, 6]
]
a, b = split(matrix)
print("A: %s" % str(a)) # Output ==> A: [[1, 0, 0], [1, 0, 0], [4, 3, 1]]
print("B: %s" % str(b)) # Output ==> B: [4, 2, 6]