以前没见过这个,但我想知道如何在Ruby中找到2D数组的两个对角线的总和。假设你有一个简单的数组,有3行3列。
array = [1,2,3,4,5,6,7,8,9]
我可以使用
将其分成三个一组array.each_slice(3).to_a
现在是
[1,2,3], [4,5,6], [7,8,9]
[1,2,3]
[4,5,6]
[7,8,9]
在这种情况下,对角线是
1 + 5 + 9 = 15
3 + 5 + 7 = 15
所以总和将是15 + 15 = 30
我以为我可以做点什么
diagonal_sum = 0
for i in 0..2
for j in 0..2
diagonal_sum += array[i][j]
end
end
答案 0 :(得分:8)
这是我的尝试:
array = [1,2,3,4,5,6,7,8,9]
sliced = array.each_slice(3).to_a
# As sliced size is 3, I took 2, i.e. 3 - 1
(0..2).map { |i| sliced[i][i] } #=> [1, 5, 9]
(0..2).map { |i| sliced[i][-i-1] } # => [3, 5, 7]
(0..2).map { |i| sliced[i][i] }.reduce :+
# => 15
(0..2).map { |i| sliced[i][-i-1] }.reduce :+
# => 15
按照上面的观察,你可以在一次迭代中解决:
left_diagonal, right_diagoal = (0..2).each_with_object([[], []]) do |i, a|
a[0] << sliced[i][i]
a[1] << sliced[i][-i-1]
end
left_diagonal.reduce(:+) # => 15
right_diagonal.reduce(:+) # => 15
添加了 OOP 代码样式:
class SquareMatrix
attr_reader :array, :order
def initialize array, n
@array = array.each_slice(n).to_a
@order = n
end
def collect_both_diagonal_elements
(0...order).collect_concat { |i| [ array[i][i], array[i][-i-1] ] }
end
def collect_left_diagonal_elements
(0...order).collect { |i| array[i][i] }
end
def collect_right_diagonal_elements
(0...order).collect { |i| array[i][-i-1] }
end
def sum_of_diagonal_elements type
case type
when :all then collect_both_diagonal_elements.reduce(0, :+)
when :right then collect_right_diagonal_elements.reduce(0, :+)
when :left then collect_left_diagonal_elements.reduce(0, :+)
end
end
end
array = [1,2,3,4,5,6,7,8,9]
sqm = SquareMatrix.new array, 3
sqm.collect_both_diagonal_elements # => [1, 3, 5, 5, 9, 7]
sqm.sum_of_diagonal_elements :all # => 30
sqm.collect_left_diagonal_elements # => [1, 5, 9]
sqm.sum_of_diagonal_elements :left # => 15
sqm.collect_right_diagonal_elements # => [3, 5, 7]
sqm.sum_of_diagonal_elements :right # => 15
答案 1 :(得分:5)
以下主要用于学术讨论:
对于主对角线,您正在寻找为“Matrix”类定义的“跟踪”功能。所以下面的方法会起作用(虽然它没有让你对方的另一个对角线,我不会打赌它的效率):
require 'Matrix'
a = array.each_slice(3).to_a
Matrix[*a].trace
要获得另一个对角线,你必须以某种方式“翻转”矩阵,所以以下似乎可行(因为each_slice
的结果是一个行数组,reverse
反转了它的顺序反转列的顺序更加困难):
Matrix[*a.reverse].trace
答案 2 :(得分:2)
我完全忘记了#map.with_index ...感谢@xlembouras,这是一个单行
first_diagonal = array.map.with_index {|row, i| row[i]} .inject :+
inverted_diagonal = array.map.with_index {|row, i| row[-i-1]} .inject :+
可以使它成为一个单行:
first_diagonal, inverted_diagonal = (array.map.with_index {|row, i| row[i]} .inject :+) , (array.map.with_index {|row, i| row[-i-1]} .inject :+)
原件:
这是一个想法,这让我觉得有一个#map_with_index方法会很棒:
从头到尾的对角线:
i = -1
array.map { |row| row[i=i+1] }.inject :+
表示最后一个对角线(假设一个正方形阵列):
i = array.length
array.map { |row| row[i=i-1] }.inject :+
答案 3 :(得分:1)
a = [1,2,3,4,5,6,7,8,9]
p a.values_at(0,2,4,4,6,8).inject(&:+) #=> 30
答案 4 :(得分:0)
我会尝试迭代数组并根据(分组)数组的长度保留我需要的值
array = [[1,2,3], [4,5,6], [7,8,9]]
dimension = array.length
array.flatten.map.with_index do |x,i|
x if [0, dimension - 1].include?(i % dimension)
end.compact.inject(:+)
#=> 30
答案 5 :(得分:0)
您不需要先申请slice
:
arr = [1,2,3,4,5,6,7,8,9]
我们将arr
视为:
1 2 3
4 5 6
7 8 9
n = Math.sqrt(arr.size).round
#=> 3
对于主对角线:
(0...arr.size).step(n+1).reduce(0) { |t,i| t+arr[i] }
#=> 15
对于非对角线:
(n-1..arr.size-n).step(n-1).reduce(0) { |t,i| t+arr[i] }
#=> 15
另一个例子:
arr = [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6]
1 2 3 4
5 6 7 8
9 0 1 2
3 4 5 6
n = Math.sqrt(arr.size).round
#=> 4
(0...arr.size).step(n+1).reduce(0) { |t,i| t+arr[i] } +
(n-1..arr.size-n).step(n-1).reduce(0) { |t,i| t+arr[i] }
#=> 14 + 14 => 28
答案 6 :(得分:0)
exec
答案 7 :(得分:-1)
def diagonal(array)
single=array.flatten
new=[]
i=array.length-1
while i < single.length-2
new << single[i]
i+=array.length-1
end
new.sum
end
p diagonal([
[1, 2, 3],
[4, 5, 6],
[7, 9, 8],
])
OUTPUT
15
That is for finding the sum of right diagonal of a 2D array