I have a list of arrays, in which each array represents a cell and the array elements are the coordinates x,y and z, the time point and the cell id. Here a sector of it:
cells=[ ...,
[ 264.847, 121.056, 30.868, 42. , 375. ],
[ 259.24 , 116.875, 29.973, 43. , 375. ],
[ 260.757, 118.574, 32.772, 44. , 375. ]]), array([[ 263.967, 154.089, 55.5 , 38. , 376. ],
[ 260.744, 152.924, 55.5 , 39. , 376. ],
[ 258.456, 151.373, 55.5 , 40. , 376. ],
...,
[ 259.086, 159.564, 48.521, 53. , 376. ],
[ 258.933, 159.796, 48.425, 54. , 376. ],
[ 259.621, 158.719, 51.606, 55. , 376. ]]), array([[ 291.647, 57.582, 28.178, 38. , 377. ],
[ 284.625, 59.221, 30.028, 39. , 377. ],
[ 282.915, 59.37 , 30.402, 40. , 377. ],
...,
[ 271.224, 58.534, 23.166, 42. , 377. ],
[ 270.048, 58.738, 21.749, 43. , 377. ],
[ 268.38 , 58.138, 20.606, 44. , 377. ]]), array([[ 87.83 , 222.144, 26.258, 39. , 378. ],
[ 99.779, 223.631, 24.98 , 40. , 378. ],
[ 104.107, 224.177, 23.728, 41. , 378. ],
...,
[ 127.778, 222.205, 23.123, 63. , 378. ],
[ 126.815, 222.347, 23.934, 64. , 378. ],
[ 127.824, 221.048, 25.508, 65. , 378. ]]),...]
minimumCellCoors = cells
maximumCellCoors = cells
centoEdge = radius+fcr_size
Now i want to change the coordinates x, y and z, so the 0.,1. and 2. element of the arrays in the list to get them in a specific grid. The user gives the spacing for x,y and z and then the operation could look like:
x_Coo=round(x_element/x)*x
y_Coo=round(y_element/y)*y
z_Coo=round(z_element/z)*z
So the real question here is, how could i do a operation on all of the elements in the array ( or in this case the first three elements in the array in the list)?
EDIT
If i use list comprehension to the list like:
[np.round((cellID[:,0]-(centoEdge+1))/x)*x for cellID in minimumCellCoors]
[np.round((cellID[:,1]-(centoEdge+1))/y)*y for cellID in minimumCellCoors]
[np.round((cellID[:,2]-(centoEdge+1))/z)*z for cellID in minimumCellCoors]
[np.round((cellID[:,0]+(centoEdge+1))/x)*x for cellID in maximumCellCoors]
[np.round((cellID[:,1]+(centoEdge+1))/x)*y for cellID in maximumCellCoors]
[np.round((cellID[:,2]+(centoEdge+1))/x)*z for cellID in maximumCellCoors]
How could i fusion the single lists of arrays to one array again?
Best regards!
First off you need to convert your list to a numpy array. It's more proper to create a numpy array instead of a list at first place. Then you can take advantage of numpy's vectorized operation support:
Here is an example:
In [45]: arr = np.arange(100).reshape(4, 5, 5)
In [46]: arr
Out[46]:
array([[[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19],
[20, 21, 22, 23, 24]],
[[25, 26, 27, 28, 29],
[30, 31, 32, 33, 34],
[35, 36, 37, 38, 39],
[40, 41, 42, 43, 44],
[45, 46, 47, 48, 49]],
[[50, 51, 52, 53, 54],
[55, 56, 57, 58, 59],
[60, 61, 62, 63, 64],
[65, 66, 67, 68, 69],
[70, 71, 72, 73, 74]],
[[75, 76, 77, 78, 79],
[80, 81, 82, 83, 84],
[85, 86, 87, 88, 89],
[90, 91, 92, 93, 94],
[95, 96, 97, 98, 99]]])
In [51]: arr[:,:,:3] = np.round(arr[:,:,:3]/5)*5
In [52]: arr
Out[52]:
array([[[ 0, 0, 0, 3, 4],
[ 5, 5, 5, 8, 9],
[10, 10, 10, 13, 14],
[15, 15, 15, 18, 19],
[20, 20, 20, 23, 24]],
[[25, 25, 25, 28, 29],
[30, 30, 30, 33, 34],
[35, 35, 35, 38, 39],
[40, 40, 40, 43, 44],
[45, 45, 45, 48, 49]],
[[50, 50, 50, 53, 54],
[55, 55, 55, 58, 59],
[60, 60, 60, 63, 64],
[65, 65, 65, 68, 69],
[70, 70, 70, 73, 74]],
[[75, 75, 75, 78, 79],
[80, 80, 80, 83, 84],
[85, 85, 85, 88, 89],
[90, 90, 90, 93, 94],
[95, 95, 95, 98, 99]]])
Note that you can also perform the operations with same length arrays as well as scalars:
For instance you could also do the following:
In [53]: arr[:,:,:3] = np.round(arr[:,:,:3]/5)*[4, 5, 6]
Related
I am doing a metanalysis of proportions using the metafor package and the rma.glmm function.
Since I the dataset is large, with many variables, I would like to reiterate the rma.glmm function through some columns of the dataframe.
This is the dataframe:
dput(data)
structure(list(event = c(5, 55, 4, 43, 2, 45, 34, 0, 34, 2, 23,
54, 45, 45, 67, 67, 78, 34, 45, 0, 34, 2, 23, 54, 45, 45, 67,
67, 78, 34, 45, 0, 34, 2, 23, 54, 45, 45), tot = c(45, 67, 89,
111, 133, 155, 177, 199, 221, 243, 265, 287, 309, 331, 353, 375,
397, 419, 441, 463, 485, 507, 529, 551, 573, 595, 617, 639, 661,
683, 705, 727, 749, 771, 793, 815, 837, 859), moderator = c("a",
"a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a",
"a", "a", "a", "a", "a", "a", "a", "a", "a", "b", "b", "b", "b",
"b", "b", "b", "b", "b", "b", "b", "b", "b", "b", "b"), x1 = c(5,
55, 4, 43, 2, 45, 34, 0, 34, 2, 23, 54, 45, 45, 67, 67, 78, 34,
45, 0, 34, 2, 23, 54, 45, 45, 67, 67, 78, 34, 45, 0, 34, 2, 23,
54, 45, 45), x2 = c(6, 56, 5, 44, 3, 46, 35, 1, 35, 3, 24, 55,
46, 46, 68, 68, 79, 35, 46, 1, 35, 3, 24, 55, 46, 46, 68, 68,
79, 35, 46, 1, 35, 3, 24, 55, 46, 46), x3 = c(7, 57, 6, 45, 4,
47, 36, 2, 36, 4, 25, 56, 47, 47, 55, 4, 43, 2, 45, 34, 0, 34,
2, 23, 54, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45
)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA,
-38L))
And I wrote the following code:
columns <- c(4,5,6) # I decide which columns of the dataframe I want analyze
n_columns <- as.numeric(length(columns))
for (var in 1:n_columns){
colname <- colnames(data[,columns[var]])
glmm<-rma.glmm(xi=colname, ni=tot, measure="PLO", data=data)
pes=predict(glmm, transf=transf.ilogit, targ=list(ni=data$tot))
}
I get the following error:
Error in ni - xi : non-numeric argument to binary operator
Basically, the code does not read the variable name which is assigned to colname.
Can anyone help? Thank you
colname is a string, which doesn't work. It's a bit like you are trying to do something like lm("x1" ~ x2, data=data).
You can simply use
glmm <- rma.glmm(xi=data[[var]], ni=tot, measure="PLO", data=data)
And you can leave out the targ=list(ni=data$tot) from predict(). This has no effect.
Let's say I have 2d array (or matrix) like,
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
And, I've to select all elements in eight directions of a certain element matrix[i][j], so I know,
up and down elements will have same j
left and right elements will have same i
back-inclined diagonal (\) elements will have same diff i-j
front-inclined diagonal (/) elements will have same sum i+j
How to select those elements, easily and efficiently? Any direct method?
For example, if my element is 4, then my selection should yield, [1, 7, 5, 6, 2, 8]. If it is, 5, then selection should be all except 5.
Edit: I've coded any solution yet, as I thought it'll be very poor, but here is my idea. Try it online!
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
res = []
i = 0
j = 1
# let [i,j] be index of my element
matrix.each_with_index{|row,r| row.each_with_index{|col,c|
res << col if c == j || r == i || r+c == i+j || r-c == i-j
}}
p res
m is the matrix you have taken from a user that is a symmetric or non-symmetric 2-dimensional array.
# inputs
m = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]
p, q = 1, 0 # co-ordinate of number 4
# code for output
i, j, result = m.size, m[0].size, []
i.times { |r| result.push(m[r][q]) if r != p }
j.times { |c| result.push(m[p][c]) if c != q }
i.times do |r|
j.times do |c|
result.push(m[r][c]) if [p,q] != [r,c] && (p-r).abs == (q-c).abs
end
end
> result
=> [1, 7, 5, 6, 2, 8]
Note: if the order of output is not needed to be preserved, we can manage with only 2 loops
Code
def extract(matrix, row, col)
last_row = matrix.size-1
last_col = matrix.first.size-1
diag_sum = row + col
diag_first_row = diag_sum - [diag_sum, last_col].min
diag_last_row = [last_row, diag_sum].min
ante_diag_diff = row - col
ante_diag_first_row = [ante_diag_diff, 0].max
ante_diag_last_row = ante_diag_diff +
[last_col, last_row - ante_diag_diff].min
arr = []
(0..last_col).each { |j| arr << matrix[row][j] unless j == col }
(0..last_row).each { |i| arr << matrix[i][col] unless i == row }
(diag_first_row..diag_last_row).each do |i|
arr << matrix[i][diag_sum - i] unless i == row
end
(ante_diag_first_row..ante_diag_last_row).each do |i|
arr << matrix[i][i - ante_diag_diff] unless i == row
end
arr
end
Example
matrix = Array.new(5) { Array.new(5) { rand(10..99) } }
#=> [[52, 29, 61, 35, 27],
# [68, 99, 67, 18, 67],
# [79, 10, 73, 15, 36],
# [49, 94, 28, 24, 53],
# [37, 26, 65, 65, 43]]
(0..4).each do |i|
(0..4).each do |j|
puts "#{i}, #{j}: #{extract(matrix,i,j)}"
end
end
i j
----------------------------------------------------------------------
0, 0: [29, 61, 35, 27, 68, 79, 49, 37, 99, 73, 24, 43]
0, 1: [52, 61, 35, 27, 99, 10, 94, 26, 68, 67, 15, 53]
0, 2: [52, 29, 35, 27, 67, 73, 28, 65, 99, 79, 18, 36]
0, 3: [52, 29, 61, 27, 18, 15, 24, 65, 67, 10, 49, 67]
0, 4: [52, 29, 61, 35, 67, 36, 53, 43, 18, 73, 94, 37]
1, 0: [99, 67, 18, 67, 52, 79, 49, 37, 29, 10, 28, 65]
1, 1: [68, 67, 18, 67, 29, 10, 94, 26, 61, 79, 52, 73, 24, 43]
1, 2: [68, 99, 18, 67, 61, 73, 28, 65, 35, 10, 49, 29, 15, 53]
1, 3: [68, 99, 67, 67, 35, 15, 24, 65, 27, 73, 94, 37, 61, 36]
1, 4: [68, 99, 67, 18, 27, 36, 53, 43, 15, 28, 26, 35]
2, 0: [10, 73, 15, 36, 52, 68, 49, 37, 61, 99, 94, 65]
2, 1: [79, 73, 15, 36, 29, 99, 94, 26, 35, 67, 49, 68, 28, 65]
2, 2: [79, 10, 15, 36, 61, 67, 28, 65, 27, 18, 94, 37, 52, 99, 24, 43]
2, 3: [79, 10, 73, 36, 35, 18, 24, 65, 67, 28, 26, 29, 67, 53]
2, 4: [79, 10, 73, 15, 27, 67, 53, 43, 24, 65, 61, 18]
3, 0: [94, 28, 24, 53, 52, 68, 79, 37, 35, 67, 10, 26]
3, 1: [49, 28, 24, 53, 29, 99, 10, 26, 27, 18, 73, 37, 79, 65]
3, 2: [49, 94, 24, 53, 61, 67, 73, 65, 67, 15, 26, 68, 10, 65]
3, 3: [49, 94, 28, 53, 35, 18, 15, 65, 36, 65, 52, 99, 73, 43]
3, 4: [49, 94, 28, 24, 27, 67, 36, 43, 65, 29, 67, 15]
4, 0: [26, 65, 65, 43, 52, 68, 79, 49, 27, 18, 73, 94]
4, 1: [37, 65, 65, 43, 29, 99, 10, 94, 67, 15, 28, 49]
4, 2: [37, 26, 65, 43, 61, 67, 73, 28, 36, 24, 79, 94]
4, 3: [37, 26, 65, 43, 35, 18, 15, 24, 53, 68, 10, 28]
4, 4: [37, 26, 65, 65, 27, 67, 36, 53, 52, 99, 73, 24]
Explanation
First observe that if the target element is in row i and column j, the elements [p,q] on the diagonal that passes through that point have the property that p+q == i+j. Similarly, the elements [p,q] on the ante-diagonal that passes through that point have the property that p-q == i-j
Suppose
row = 1
col = 2
then
last_row = matrix.size-1
#=> 4
last_col = matrix.first.size-1
#=> 4
diag_sum = row + col
#=> 3
diag_first_row = diag_sum - [diag_sum, last_col].min
#=> 0
diag_last_row = [last_row, diag_sum].min
#=> 3
ante_diag_diff = row - col
#=> -1
ante_diag_first_row = [ante_diag_diff, 0].max
#=> 0
ante_diag_last_row = ante_diag_diff +
[last_col, last_row - ante_diag_diff].min
#=> 3
The remaining calculations are straightforward.
Here's a variant of the above that uses less code and may be slightly less efficient.
def extract(matrix, row, col)
row_range = 0..matrix.size-1
col_range = 0..matrix.first.size-1
diag_sum = row + col
ante_diag_diff = row - col
arr = []
col_range.each { |j| arr << matrix[row][j] unless j == col }
row_range.each do |i|
next if i == row
arr << matrix[i][col]
j = diag_sum - i
arr << matrix[i][j] if col_range.cover?(j)
j = i - ante_diag_diff
arr << matrix[i][j] if col_range.cover?(j)
end
arr
end
Here is sample code, you can modify/simplify it further
class Matrix
attr_reader :arr, :ele
def initialize(arr, ele)
#arr = arr
#ele = ele
end
def find_elements
position = arr.flatten.index(ele)
len = arr.length
x = position % len
y = position / len
horizontal_elements(y) + vertical_elements(x, y, len) + remaining_elements(x, y, len)
end
def horizontal_elements y
arr[y] - [ele]
end
def vertical_elements x, y, len
rows = (0..(len-1)).to_a - [y]
rows.map{|row| arr[row][x] }
end
def remaining_elements(x, y, len)
rows = []
rows << y + 1 if y + 1 < len
rows << y - 1 if y - 1 >= 0
c_rows = []
c_rows << x + 1 if x + 1 < len
c_rows << x - 1 if x - 1 >= 0
rows.map{|row| c_rows.map{|c_row| arr[row][c_row] } }.flatten
end
end
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
ele = 4
(1..9).each do |i|
puts '*' * 20
puts "For #{i}"
puts Matrix.new(matrix, i).find_elements.inspect
puts '*' * 20
end
O/P will be something like following
Desktop $ ruby something.rb
********************
For 1
[2, 3, 4, 7, 5]
********************
********************
For 2
[1, 3, 5, 8, 6, 4]
********************
********************
For 3
[1, 2, 6, 9, 5]
********************
********************
For 4
[5, 6, 1, 7, 8, 2]
********************
********************
For 5
[4, 6, 2, 8, 9, 7, 3, 1]
********************
********************
For 6
[4, 5, 3, 9, 8, 2]
********************
********************
For 7
[8, 9, 1, 4, 5]
********************
********************
For 8
[7, 9, 2, 5, 6, 4]
********************
********************
For 9
[7, 8, 3, 6, 5]
********************
A recursive way
I'd like to propose a different approach, not tested if it is more or less efficient but can provide some control on order and more.
Lets start with this matrix, where elements tell their indexing:
mat = [
['00', '01', '02'],
['10', '11', '12'],
['20', '21', '22'],
['30', '31', '32']
]
And define an helper method just to get the shape of the matrix and to check which is well formed:
def shape(mat)
raise 'Out of shape' if mat.map(&:size).uniq.size > 1
return mat.size, mat[0].size
end
Implementation
Now, let's define a method that takes as input the starting point, the limits of the matrix (shape) and the direction.
def walk(i_0, j_0, i_max, j_max, direction, res=[])
d_i, d_j = direction
next_step = [i_0 + d_i, j_0 + d_j]
if [-1, i_max].include?(next_step[0]) || [-1, j_max].include?(next_step[1])
return res
end
res << next_step
i_0, j_0 = next_step
walk(i_0, j_0, i_max, j_max, direction, res)
end
The method returns the list of indexes starting from the origin and walking along the direction.
Usage examples
Example 1
i_0, j_0 = [2, 0]
i_max, j_max = shape(mat)
direction = [-1, 1]
walk(i_0, j_0, *shape(mat), direction)
#=> [[1, 1], [0, 2]]
Example 2
You can use it to extract the indexes given a list of directions.
It's possible to arrange the list of directions to give a scan order (clockwise, cclockwise) or just skip some directions, as you will.
directions = [[1, 0], [-1, 0], [0, 1], [0, -1], [1, 1], [1, -1], [-1, 1], [-1, -1]]
i_0, j_0 = [2, 0]
directions = [[1, 0], [-1, 0], [0, 1], [0, -1], [1, 1], [1, -1], [-1, 1], [-1, -1]]
directions.flat_map { |direction| walk(i_0, j_0, *shape(mat), direction) }
#=> [[3, 0], [1, 0], [0, 0], [2, 1], [2, 2], [3, 1], [1, 1], [0, 2]]
Example 3
(Which is an extension of example 2)
You can directly get the elements from the matrix:
res = directions.flat_map do |direction|
walk(i_0, j_0, *shape(mat), direction).map do |coords|
i, j = coords
mat[i][j]
end
end
res
#=> ["30", "10", "00", "21", "22", "31", "11", "02"]
It can be possible to use a longer step (eg. direction = [2, 2]) upgrading the walk method.
I've setup an authentication process using Google Firebase. I'm now looking to start working with the Firestore database - because I need multiple collections to work with - and have a large amount of data in a JSON file that needs importing.
The JSON file looks like this. I'll post just the first two entries but there are 60 total and not something that's feasible to just type in myself.
If someone could walk me through the steps on how to utilize a script for this issue, that would be greatly appreciated. Thanks!
I've tried to utilize some of the other posts on Stack but it's the use of scripts that has me all tripped up.
[
{
"FirstName": "Nickeil",
"LastName": "Alexander-Williams",
"Position": 2,
"Age": 19,
"CollegeYear": 2,
"Height": 77,
"DisplayHeight": "6-5",
"Weight": 205,
"College": "Virginia Tech",
"Consistency": 46,
"Greed": 72,
"Loyalty": 58,
"PlayForWinner": 16,
"PlayingTime": 26,
"Personality": 53,
"Durability": 47,
"WorkEthic": 75,
"DunkRate": 56,
"RARate": 3,
"DriveKick": 58,
"DriveShot": 0,
"PostUp": 0,
"PullUp": 17,
"CS": 32,
"Pass": 68,
"LocATB": 30,
"LocCorner": 81,
"LocMidrange": 27,
"LocPaint": 42,
"FG_RA": 58,
"FG_ITP": 58,
"FG_MID": 31,
"FG_COR": 18,
"FG_ATB": 67,
"FT": 0,
"Scoring": 35,
"Passing": 40,
"Handling": 41,
"OReb": 51,
"DReb": 61,
"Block": 52,
"Steal": 23,
"DrawFoul": 5,
"Defender": 54,
"Discipline": 75,
"BballIQ": 65,
"FG_RA_POT": 65,
"FG_ITP_POT": 65,
"FG_MID_POT": 38,
"FG_COR_POT": 25,
"FG_ATB_POT": 74,
"FT_POT": 7,
"Scoring_POT": 42,
"Passing_POT": 47,
"Handling_POT": 48,
"OReb_POT": 58,
"DReb_POT": 68,
"Block_POT": 59,
"Steal_POT": 30,
"DrawFoul_POT": 12,
"Defender_POT": 61,
"Discipline_POT": 82,
"BballIQ_POT": 72
},
{
"FirstName": "RJ",
"LastName": "Barrett",
"Position": 2,
"Age": 19,
"CollegeYear": 1,
"Height": 78,
"DisplayHeight": "6-6",
"Weight": 210,
"College": "Duke",
"Consistency": 61,
"Greed": 83,
"Loyalty": 77,
"PlayForWinner": 80,
"PlayingTime": 81,
"Personality": 76,
"Durability": 44,
"WorkEthic": 79,
"DunkRate": 80,
"RARate": 17,
"DriveKick": 51,
"DriveShot": 28,
"PostUp": 20,
"PullUp": 40,
"CS": 45,
"Pass": 35,
"LocATB": 40,
"LocCorner": 84,
"LocMidrange": 35,
"LocPaint": 54,
"FG_RA": 54,
"FG_ITP": 54,
"FG_MID": 39,
"FG_COR": 26,
"FG_ATB": 66,
"FT": 2,
"Scoring": 40,
"Passing": 27,
"Handling": 36,
"OReb": 57,
"DReb": 65,
"Block": 37,
"Steal": 39,
"DrawFoul": 13,
"Defender": 61,
"Discipline": 54,
"BballIQ": 58,
"FG_RA_POT": 61,
"FG_ITP_POT": 61,
"FG_MID_POT": 46,
"FG_COR_POT": 33,
"FG_ATB_POT": 73,
"FT_POT": 9,
"Scoring_POT": 47,
"Passing_POT": 34,
"Handling_POT": 43,
"OReb_POT": 64,
"DReb_POT": 72,
"Block_POT": 44,
"Steal_POT": 46,
"DrawFoul_POT": 20,
"Defender_POT": 68,
"Discipline_POT": 61,
"BballIQ_POT": 65
},
.
.
.
]
I faced same issue while code. For import JSON to your firebase DB have no specific method but you can insert it by script. For that purpose I make this script. This might help you too.
const fcm = require('nodefire-realtime');
//For Initialize Firebase DB
let serviceAccountKey = require("./serviceAccountKey.json");
let dbUrl = "https://<Your-project-id>.firebaseio.com/";
fcm.init(dbUrl, serviceAccountKey);
const data = require('./<your-JSON-file-name>.json');
//For insert
let dbReference = 'data/user/';
let data =data;
fcm.insert(data, dbReference);
Just make a simple JS file e.g. app.js and paste above code to it. You can get serviceAccountKey.json from project settings(firebase).
And if you get stuck with this package, follow steps from nodefire-realtime. I wish this will help.
I have a double array where I need to search the first row using a jtextfield input to get the index (position of [i]), then use that index number to identify the second row location and use the variable in the second array row. I'm using this to get the Gross Profit Margin Multiplier in second row of the array based on the position of the percentage margin in the first row array.
Do appreciate your help. I have searched other array links but they deal ether with the locations and not the contents of the locations.
public void getMarginArray(){
double[][] margn = {{10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50},
{1.11, 1.12, 1.13, 1.15, 1.16, 1.17, 1.19, 1.20, 1.22, 1.23, 1.25, 1.26, 1.28, 1.30, 1.31, 1.33, 1.35, 1.37, 1.39, 1.41, 1.43, 1.45, 1.47, 1.49, 1.51, 1.55, 1.56, 1.59, 1.61, 1.64, 1.67, 1.70, 1.72, 1.75, 1.79, 1.82, 1.86, 1.89, 1.92, 1.96, 2.00}};
Double MARG = Double.parseDouble( jtxtfldMargin.getText());
Double MAR1;
for (int i=0; i<margn.length; i++){
if (margn[0][i] ==MARG){
Double MAR1=margn[1][i];
System.out.println(margn[0][i]);
System.out.println(margn[1][i]);
System.out.println(MAR1);
};
};
I was able to get what I needed by changing to two separate arrays. Now when the first array matches the text field, the location is used for the second array to get the multiplier:
public void getMarginArray(){
double[] doubleArray1 = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50};
double[] doubleArray2 = {1.11, 1.12, 1.13, 1.15, 1.16, 1.17, 1.19, 1.20, 1.22, 1.23, 1.25, 1.26, 1.28, 1.30, 1.31, 1.33, 1.35, 1.37, 1.39, 1.41, 1.43, 1.45, 1.47, 1.49, 1.51, 1.55, 1.56, 1.59, 1.61, 1.64, 1.67, 1.70, 1.72, 1.75, 1.79, 1.82, 1.86, 1.89, 1.92, 1.96, 2.00};
Double MARG = Double.parseDouble( jtxtfldMargin.getText());
Double margMult;
for(int i = 0; i<doubleArray1.length; i++){
for(int j = 0; j<doubleArray2.length;j++){
if(doubleArray1[i] == MARG ){
margMult = doubleArray2[i];
System.out.println(margMult);
}
}
}
}
I have a two-dimensional array with sub-arrays of equal size, for example:
array = [
[10, 12, 15 ,17], [16, 32, 65, 47], [45, 48, 41, 23],
[36, 25, 74, 98], [32, 19, 66, 88]
]
I would like to create a new array by summing the corresponding elements of every 4th sub-array, i.e. the elements that are "on top of each other" in the above example:
new_array = [
[10 + 36, 12 + 25, 15 + 74, 17 + 98],
[16 + 32, 32 + 19, 65 + 66, 47 + 88],
[45, 48, 41, 23]
]
These are just examples, the actual arrays can be larger.
Complete Matrix
You can use each_slice, transpose, map and transpose again to navigate your matrix.
The code first uses join('+') to show what is being calculated :
array= [[10,12,15,17],[16,32,65,47],[45,48,41,23],[36,25,74,98],[32,19,66,88],[1,2,3,4]]
array.each_slice(3).to_a.transpose.map{|r| r.transpose.map{|x| x.join('+')}}
# => [["10+36", "12+25", "15+74", "17+98"], ["16+32", "32+19", "65+66", "47+88"], ["45+1", "48+2", "41+3", "23+4"]]
array.each_slice(3).to_a.transpose.map{|r| r.transpose.map{|x| x.inject(:+)}}
# => [[46, 37, 89, 115], [48, 51, 131, 135], [46, 50, 44, 27]]
Warning!
You need to carefully select the each_slice parameter to suit your original array. transpose might raise an exception otherwise :
array = [[10,12,15,17],[19,32,65,47],[45,48,41,23],[36,25,74,98],[10,12,15,17],[16,98,65,47],[69,48,65,23],[66,25,74,98]]
array.each_slice(3).to_a.transpose.map{|r| r.transpose.map{|x| x.inject(:+)}}
#=> IndexError: element size differs (2 should be 3)
array.each_slice(4).to_a.transpose.map{|r| r.transpose.map{|x| x.inject(:+)}}
#=> [[20, 24, 30, 34], [35, 130, 130, 94], [114, 96, 106, 46], [102, 50, 148, 196]]
Incomplete Matrix
If the matrix size isn't a multiple of width :
array = [
[10, 12, 15 ,17], [16, 32, 65, 47], [45, 48, 41, 23],
[36, 25, 74, 98], [32, 19, 66, 88]
]
you could add subarrays full of 0s to get :
matrix = [
[10, 12, 15 ,17], [16, 32, 65, 47], [45, 48, 41, 23],
[36, 25, 74, 98], [32, 19, 66, 88], [ 0, 0, 0, 0]
]
Array#fill does the job :
def maxtrix_column_sums(array, width)
size = array.size
size2 = array.first.size
missing = (-size) % width
matrix = array.dup.fill(Array.new(size2, 0), size...size + missing)
matrix.each_slice(width).to_a.transpose.map { |r| r.transpose.map { |x| x.join('+') } }
end
p maxtrix_column_sums(array, 3)
#=> [["10+36", "12+25", "15+74", "17+98"], ["16+32", "32+19", "65+66", "47+88"], ["45+0", "48+0", "41+0", "23+0"]]
Here's a variation of Eric Duminil's answer using zip instead of transpose to account for an "odd" number of sub-arrays:
first, *rest = array.each_slice(3).to_a
first.zip(*rest).map { |r| r.compact.transpose.map { |x| x.inject(:+) } }
#=> [[46, 37, 89, 115], [48, 51, 131, 135], [45, 48, 41, 23]]
How it works:
each_slice separates the array into groups of 3:
array.each_slice(3).to_a
#=> [
# [[10, 12, 15, 17], [16, 32, 65, 47], [45, 48, 41, 23]],
# [[36, 25, 74, 98], [32, 19, 66, 88]]
# ]
first.zip(*rest) combines the first slice "column"-wise with the remaining slices, adding nil when a slice is missing:
first.zip(*rest)
#=> [
# [[10, 12, 15, 17], [36, 25, 74, 98]],
# [[16, 32, 65, 47], [32, 19, 66, 88]],
# [[45, 48, 41, 23], nil]
# ]
The map / compact / transpose part then restructures the sub-array while getting rid of nil values:
first.zip(*rest).map { |r| r.compact.transpose }
#=> [
# [[10, 36], [12, 25], [15, 74], [17, 98]],
# [[16, 32], [32, 19], [65, 66], [47, 88]],
# [[45], [48], [41], [23]]
# ]
And inject(:+) finally sums the inner elements.