I've been scanning the forums and haven't found an answer yet that I can apply to my situation. I need to be able to take an n by n array and transpose it in Python-3. The example given is that I have this list input into the function:
[[4, 2, 1], ["a", "a", "a"], [-1, -2, -3]] and it needs to be transposed to read:
[[4, 'a', -1], [2, 'a', -2], [1, 'a', -3]] So basically reading vertically instead of horizontally.
I CANNOT use things like zip or numpy, I have to make my own function.
Been rattling my brain at this for two nights and it's a huge headache. If anyone could help and then provide an explanation so I can learn it, I'd be grateful.
Edit:
I should add for reference sake that the argument variable is M. The function we're supposed to write is trans(M):
A one-liner:
def trans(M):
return [[M[j][i] for j in range(len(M))] for i in range(len(M[0]))]
result:
>>> M = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> trans(M)
[[1, 4, 7], [2, 5, 8], [3, 6, 9]
# or for a non-square matrix:
>>> N = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
>>> trans(N)
[[1, 4, 7, 10], [2, 5, 8, 11], [3, 6, 9, 12]]
Additional Note: If you look up the tutorial on list comprehension, one of the examples is in fact transposition of a matrix array.
A variant that should work for matrices with irregular row lengths:
m=[[3, 2, 1],
[0, 1],
[2, 1, 0]]
m_T = [ [row[c] for row in m if c < len(row)] for c in range(0, max([len(row) for row in m])) ]
Here is an in place solution that works for square matrices:
def trans(M):
n = len(M)
for i in range(n - 1):
for j in range(i + 1, n):
M[i][j], M[j][i] = M[j][i], M[i][j]
Example Usage:
def print_matrix(M):
for row in M:
for ele in row:
print(ele, end='\t')
print()
M = [[4, 2, 1], ["a", "a", "a"], [-1, -2, -3]]
print('Original Matrix:')
print_matrix(M)
trans(M)
print('Transposed Matrix:')
print_matrix(M)
Output:
Original Matrix:
4 2 1
a a a
-1 -2 -3
Transposed Matrix:
4 a -1
2 a -2
1 a -3
y=([1,2], [3,4], [5,6])
transpose=[[row[i] for row in y] for i in range(len(y[0]))]
the output is
[[1, 3, 5], [2, 4, 6]]
You can also use the function in numpy to transpose - if you need the answer as a list it is straightforward to convert back using tolist:
from numpy import transpose
M = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
transpose(M).tolist()
the output is
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Haven't timed it (no time!) but I strongly suspect this will be a lot faster than iterators for large arrays, especially if you don't need to convert back to a list.
Related
For a given array of integers, perform operations on the array. Return the resulting array after all operations have been applied in the order given. Each operation contains two indices. Reverse the subarray between those zero-based indices, inclusive.
1: arr is : [1, 2, 3] 1: operations is : [[0, 2], [1, 2], [0, 2]]
2: arr is : [640, 26, 276, 224, 737, 677, 893, 87, 422, 30] 2: operations is : [[0, 9], [2, 2], [5, 5], [1, 6], [5, 6], [5, 9], [0, 8], [6, 7], [1, 9], [3, 3]]
can any one help in solving this question.
Start like this:
[1, 2, 3] -> [3, 2, 1] # first: reverse array between index 0 and 2
-> [3, 1, 2] # then: reverse array between index 1 and 2
etc.
I hope you got the idea.
How can I slice the last 2 columns of a numpy array?
for example:
A = np.array([[1, 2, 3], [4, 5, 6]])
and I want to get B as the last 2 columns of A which is [[2, 3], [5, 6]]
I know that I can index it from start of the array such as B = A[:, 1:3]. But I am looking for a general form to slice A by indexing from the end as the number of columns for A changes in my case.
Here you go
>>> A = np.array([[1, 2, 3],[4, 5, 6]])
>>> A[:,[-2,-1]]
array([[2, 3],
[5, 6]])
A generalised method to get the last n rows can be
>>> A = np.array([[1, 2, 3,4],[4, 5, 6,7]])
>>> A[:,-3:]
array([[2, 3, 4],
[5, 6, 7]])
I have an array
array_a1 = [9,43,3,6,7,0]
which I'm trying to get the sort indices out of, i.e. the answer should be
array_ordered = [6, 3, 4, 5, 1, 2]
I want to do this as a function, so that
def order (array)
will return array_ordered
I have tried implementing advice from Find the index by current sort order of an array in ruby but I don't see how I can do what they did for an array :(
if there are identical values in the array, e.g.
array_a1 = [9,43,3,6,7,7]
then the result should look like:
array_ordered = [3, 4, 5, 6, 1, 2]
(all indices should be 0-based, but these are 1-based)
You can do it this way:
[9,43,3,6,7,0].
each_with_index.to_a. # [[9, 0], [43, 1], [3, 2], [6, 3], [7, 4], [0, 5]]
sort_by(&:first). # [[0, 5], [3, 2], [6, 3], [7, 4], [9, 0], [43, 1]]
map(&:last)
#=> [5, 2, 3, 4, 0, 1]
First you add index to each element, then you sort by the element and finally you pick just indices.
Note, that array are zero-indexed in Ruby, so the results is less by one comparing to your spec.
You should be able to just map over the sorted array and lookup the index of that number in the original array.
arr = [9,43,3,6,7,0]
arr.sort.map { |n| arr.index(n) } #=> [5, 2, 3, 4, 0, 1]
Or if you really want it 1 indexed, instead of zero indexed, for some reason:
arr.sort.map { |n| arr.index(n) + 1 } #=> [6, 3, 4, 5, 1, 2]
array_a1 = [9,43,3,6,7,0]
array_a1.each_index.sort_by { |i| array_a1[i] }
#=> [5, 2, 3, 4, 0, 1]
If array_a1 may contain duplicates and ties are to be broken by the indices of the elements (the element with the smaller index first), you may modify the calculation as follows.
[9,43,3,6,7,7].each_index.sort_by { |i| [array_a1[i], i] }
#=> [2, 3, 4, 5, 0, 1]
Enumerable#sort_by compares two elements with the spaceship operator, <=>. Here, as pairs of arrays are being compared, it is the method Array#<=> that is used. See especially the third paragraph of that doc.
I need to get all submatrices of the 2D array and to do the manipulation for each submatrix. So I created example matrix:
M3 = [list(range(5)) for i in range(6)]
[[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4]]
I need to capture 3 rows and 3 columns and then shift this "window" till I get all submatrices. The first submatrix would be:
[[0, 1, 2],
[0, 1, 2],
[0, 1, 2]]
and the last one is:
[[2, 3, 4],
[2, 3, 4],
[2, 3, 4]]
For this matrix I need 12 submatrices. However, I become more using code with which I tried to solve the problem:
for j in range(len(M3[0])-3):
for i in range(len(M3)-3):
for row in M3[0+j:3+j]:
X_i_j = [row[0+i:3+i] for row in M3[0+j:3+j]]
print(X_i_j)
I get 18 but not 12 (with two duplicates of each submatrix):
[[0, 1, 2], [0, 1, 2], [0, 1, 2]]
[[0, 1, 2], [0, 1, 2], [0, 1, 2]]
[[0, 1, 2], [0, 1, 2], [0, 1, 2]]
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]
...
[[2, 3, 4], [2, 3, 4], [2, 3, 4]]
[[2, 3, 4], [2, 3, 4], [2, 3, 4]]
And with this sample of code I get 6 submatrices with 1 duplicate for each:
for i in range(len(M3)-3):
for j in range(len(M3[0])-3):
X_i_j = [row[0+i:3+i] for row in M3[0+j:3+j]]
print(X_i_j)
I do not see what is wrong with it and why I get the duplicates. How can I get all sub matrices of 2D array without numpy for this case?
Your code is working ( with change of order of vars and constants ):
for j in range(len(M3)-2):
for i in range(len(M3[0])-2):
X_i_j = [row[0+i:3+i] for row in M3[0+j:3+j]]
print('=======')
for x in X_i_j:
print(x)
I would solve it slightly different.
a function to read y-number-of-rows
then a function to read x-number-of-columns from those rows, which then is your sub.
This would work for any (2D) array / sub-array
Sample:
def read_y_rows(array, rows, offset):
return array[offset:rows + offset]
def read_x_cols(array, cols, offset):
return list(row[offset:cols + offset] for row in array)
def get_sub_arrays(array, x_dim_cols, y_dim_rows):
"""
get 2D sub arrays by x_dim columns and y_dim rows
from 2D array (list of lists)
"""
result = []
for start_row in range(len(array) - y_dim_rows + 1):
y_rows = read_y_rows(array, y_dim_rows, start_row)
for start_col in range(len(max(array, key=len)) - x_dim_cols + 1):
x_columns = read_x_cols(y_rows, x_dim_cols, start_col)
result.append(x_columns)
return result
to use it you could do:
M3 = [list(range(5)) for i in range(6)]
sub_arrays = get_sub_arrays(M3, 3, 3) ## this would also work for 2x2 arrays
the sub_arrays is again a list of lists, containing all found subarrays, you could print them like this:
for sub_array in sub_arrays:
print()
for row in sub_array:
print(row)
I know it is a lot more code than above, just wanted to share this code.
I have array and sum_of_two:
array = [10, 5, 1, 9, 7, 8, 2, 4, 6, 9, 3, 2, 1, 4, 8, 7, 5]
sum_of_two = 10
I'm trying to find the combination of two integers in array whose latter element of the two appears the earliest among those of such combinations whose sum equals sum_of_two. For example, both [5, 5] and [1, 9] are candidates for such combinations, but 9 of [1, 9] (which appears later than 1 in array) appears earlier than the second 5 of [5, 5] (which is the last element in array). So I would like to return [1, 9].
I tried using combination and find:
array.combination(2).find{|x,y| x + y == sum_of_two} #=> [5, 5]
However, it returns a combination of the first integer in the array, 5 , and another integer further along the array, also 5.
If I use find_all instead of find, I get all combinations of two integers that add up to sum_of_two:
array.combination(2).find_all{|x,y| x + y == sum_of_two}
#=> [[5, 5], [1, 9], [1, 9], [9, 1], [7, 3], [8, 2], [8, 2], [2, 8], [4, 6], [6, 4], [9, 1], [3, 7], [2, 8]]
But then I'm not sure how to get the first one.
I would use Set (which would be a bit more efficient than using Array#include?) and do something like this:
array = [10, 5, 1, 9, 7, 8, 2, 4, 6, 9, 3, 2, 1, 4, 8, 7, 5]
sum_of_two = 10
require 'set'
array.each_with_object(Set.new) do |element, set|
if set.include?(sum_of_two - element)
break [sum_of_two - element, element]
else
set << element
end
end
#=> [1, 9]
x = array.find.with_index{|e, i| array.first(i).include?(sum_of_two - e)}
[sum_of_two - x, x] # => [1, 9]
Array#combination(n) does not give the elements in the order you want, so you must build the pairs yourself. It's easy if you begin from the second index. A O(n) lazy implementation, and let's call the input xs:
pairs = (1...xs.size).lazy.flat_map { |j| (0...j).lazy.map { |i| [xs[i], xs[j]] } }
first_matching_pair = pairs.detect { |i, j| i + j == 10 }
#=> [1, 9]