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])
Related
My task is to replace all the elements whose both indexes are odd with 1, and all the elements whose both indexes are even with -1.
You can replace elements by using a double index like: array[y][x] if array is list of lists.
This is a example:
array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
length = len(array)
for y in range(length):
for x in range(length):
if y % 2 and x % 2:
array[y][x] = 1
elif y % 2 == 0 and x % 2 == 0:
array[y][x] = 0
print(array)
This will output: [[0, 2, 0], [4, 1, 6], [0, 8, 0]]
Answer:
for i in range(row):
for j in range(col):
if (i%2==0 and j%2==0):
array[i][j] = -1
elif (i%2 and j%2):
array[I][j] = 1
row => length of nested array
col => length of the array
test = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
def replace(arr):
for i in range(len(arr)):
for j in range(len(arr)):
if i % 2 and j % 2: # checks if both indexes are odd
test[i][j] = 1
elif not i % 2 and not j % 2: # checks if both indexes are even
test[i][j] = -1
return arr
print(replace(test)) # [[-1, 2, -1], [4, 1, 6], [-1, 8, -1]]
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.
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]]
Say I had a list:
lis = [4, 8, 2, 4, 6]
And I want to go through each value in the list and double it but If I come across the number 2, after I double it I should skip the next number and only double the on after. For example, in the end my list should look like this.
lis = [8, 16, 4, 4, 12]
Can this be possible with a for loop?
The algorithm boils down what number you are using to double the items in the list (1 or 2). Here is my take on this problem:
lis = [4, 8, 2, 4, 6]
def double_with_my_condition(l, doubler=2):
for i in l:
yield i * doubler
if i == 2:
doubler = 1
continue
doubler = 2
new_lis = [*double_with_my_condition(lis)]
print(new_lis)
Outputs:
[8, 16, 4, 4, 12]
I wrote out a really simple solution that should be easy to understand since it appears you are a beginner
lis = [4, 8, 2, 4, 6]
new_lis = []
i = 0
while (i < len(lis)):
new_lis.append(lis[i] * 2)
if (lis[i] == 2):
if (i+1 < len(lis)):
new_lis.append(lis[i+1])
i = i+1
i = i+1
print(new_lis)
This creates a new list, loops through the old list, appends the doubled value to the new list, skips a number if the value at the index is 2.
This will work!
Method-1:
lis = [4, 8, 2, 4, 6]
for i in range(len(lis)-1, -1, -1):
if(lis[i-1] == 2):
continue
else:
lis[i] = lis[i]*2
lis
Method-2:
lis1 = [4, 8, 2, 4, 6]
indices = [i+1 for i, x in enumerate(lis1) if x == 2] #Storing indices of next to 2
lis2 = [i*2 for i in lis1]
for i in indices:
lis2[i] = lis1[i] # replacing the previous values
print(lis2)
You can also use list comprehensions
lis = [4, 8, 2, 4, 6]
print([lis[x] if lis[x - 1] == 2 else lis[x] * 2 for x in range(len(lis))])