我正在研究一个项目,该项目涉及检查输入是否为n维矩阵(并找到其维度),如果没有则会引发错误。例如
arr = [ [[1,2],[3,4]], [[5,6],[7,8]], [[9,10],[11,12]] ]
是维度矩阵[3 2 2]。最简单的通用方法是什么?
答案 0 :(得分:3)
Ruby实际上有Matrix class,也许可以使用它?
Matrix[[[1,2],[3,4]], [[5,6],[7,8]], [[9,10],[11,12]]]
#=> Matrix[[[1, 2], [3, 4]], [[5, 6], [7, 8]], [[9, 10], [11, 12]]]
Matrix[[1,2], [3]]
# ExceptionForMatrix::ErrDimensionMismatch: row size differs (1 should be 2)
答案 1 :(得分:3)
递归解决方案,但不是很容易理解。
arr1 = [[[1, 2], [3, 4]], [[5, 6], [7, 8]], [[9, 10], [11, 12]]]
arr2 = [[[1, 2], [4]], [6, [7, 8]]]
def dimensions(m)
if m.any? { |e| e.is_a?(Array) }
d = m.group_by { |e| e.is_a?(Array) && dimensions(e) }.keys
[m.size] + d.first if d.size == 1 && d.first
else
[m.size]
end
end
dimensions(arr1) #=> [3, 2, 2]
dimensions(arr2) #=> nil
<强>释强>
算法首先检查嵌套数组m.any? { |e| e.is_a?(Array) }
。
如果没有嵌套数组,那么您只有一个维度,并通过[m.size]
块中的else
返回给定数组的大小。
dimensions([1,2,3]) #=> [3]
如果至少有一个嵌套数组,则必须确保所有元素都是数组,并且数组具有相同的维度。此检查是通过d = m.group_by { |e| e.is_a?(Array) && dimensions(e) }.keys
完成的,[[5, 6], [7, 8]].group_by { |e| ... }.keys
#=> [[2]], all nested array dimensions are equal [2]
[[1, 2], [4]].group_by { |e| ... }.keys
#=> [[1], [2]], different dimensions
[6, [7, 8]].group_by { |e| ... }.keys
#=> [false, [2]], an element isn't an array
按尺寸对所有元素进行分组。
group_by
该算法仅采用if d.size == 1 && d.first
和[m.size] + d.first
的有效结果,并通过nil
将嵌套数组的维度添加到结果中。
如果有多个键元素或只有nil
这意味着所有嵌套数组都无效,则它会隐式返回python
ImportError at /post/5/comment/
cannot import name 'CommentForm'
Request Method: GET
Request URL: http://localhost:8000/post/5/comment/
Django Version: 1.8
Exception Type: ImportError
Exception Value:
cannot import name 'CommentForm'
Exception Location: E:\pywork\djangogirls\blog\views.py in <module>, line 6
Python Executable: E:\Python35\python.exe
Python Version: 3.5.0
Python Path:
['E:\\pywork\\djangogirls',
'E:\\Python35\\lib\\site-packages\\django_debug_toolbar-1.4-py3.5.egg',
'E:\\Python35\\lib\\site-packages\\sqlparse-0.1.19-py3.5.egg',
'E:\\Python35\\python35.zip',
'E:\\Python35\\DLLs',
'E:\\Python35\\lib',
'E:\\Python35',
'E:\\Python35\\lib\\site-packages']
Server time: Thu, 16 Jun 2016 17:02:11 +0800
。
就是这样。
答案 2 :(得分:2)
如果你看一下
的例子[[[1,2],[3,4]], [[5,6],[7,8]], [[9,10],[11,12]]]
和维度[3, 2, 2]
您可以按以下方式逐个元素地阅读维度:
这表明可以通过在每个深度级别调用Array#size
来计算维度。
上述方法可以实现为:
def unchecked_matrix_dimension(matrix)
dimension = []
while matrix.is_a?(Array)
dimension << matrix.size
matrix = matrix[0]
end
dimension
end
此代码仅查看第一个位置的元素,因此[[1], []]
报告的维度为[2, 1]
,但它根本不是有效矩阵。
假设我们有一个函数matrix_dimension?(matrix, dimension)
,如果true
属于指定的matrix
,则返回dimension
,否则返回false
。我们可以用它来检测这样的无效矩阵:
def matrix_dimension(matrix)
dimension = unchecked_matrix_dimension(matrix)
if matrix_dimension?(matrix, dimension)
dimension
else
nil
end
end
事实证明,写matrix_dimension?
很容易!
我们可以以递归方式定义matrix_dimension?
:
dimension == []
,那么我们期望标量值。dimension == [d_1]
,我们预计会有一系列d_1
维度为[]
的子矩阵(即标量)。dimension == [d_1, d_2]
,我们预计会有d_1
个维度[d_2]
的子矩阵数组(即d_2
个标量数组)。一般情况下,如果dimension == [d_1, ..., d_n]
,我们期望一组d_1
元素,并且这些元素中的每一个都应该具有维度[d_2, ..., d_n
。在Ruby中:
def matrix_dimension?(matrix, dimension)
if dimension == []
!matrix.is_a?(Array)
else
matrix.size == dimension[0] &&
matrix.all? { |submatrix| matrix_dimension?(submatrix, dimension[1..-1]) }
end
end
根据matrix_dimension?
的定义,如果参数是有效的n维矩阵,则matrix_dimension
函数将返回维度,否则返回nil
。
def unchecked_matrix_dimension(matrix)
dimension = []
while matrix.is_a?(Array)
dimension << matrix.size
matrix = matrix[0]
end
dimension
end
def matrix_dimension(matrix)
dimension = unchecked_matrix_dimension(matrix)
if matrix_dimension?(matrix, dimension)
dimension
else
nil
end
end
def matrix_dimension?(matrix, dimension)
if dimension == []
!matrix.is_a?(Array)
else
matrix.size == dimension[0] &&
matrix.all? { |submatrix| matrix_dimension?(submatrix, dimension[1..-1]) }
end
end
答案 3 :(得分:1)
不使用Matrix
类:
input = [ [[1,2],[3,4]], [[5,6],[7,8]], [[9,10],[11,12]] ]
m3 = input.map { |a| a.map(&:size) }
m2 = input.map(&:size)
m1 = input.size
checker = ->(e, memo) { raise unless e == memo; e }
[ m1, m2.reduce(&checker), m3.reduce(&checker).reduce(&checker) ]
#⇒ [3, 2, 2]
答案 4 :(得分:1)
我用递归解决了这个问题。如果数组表示n维矩阵,则返回维数组;否则返回false
。
<强>代码强>
def ndim_matrix(arr)
return false if arr.map(&:size).uniq != [arr.first.size]
arrays, literals = arr.partition { |e| e.is_a? Array }
return [arr.size] if arrays.empty?
return false unless literals.empty?
res = arr.map { |e| ndim_matrix(e) }.uniq
return false if res.size > 1 or res == [false]
[arr.size, *res.first]
end
<强>实施例强>
arr = [1,2]
ndim_matrix(arr)
#=> [2]
arr = [ [1,2,3],[4,5,6] ]
ndim_matrix(arr)
#=> [2,3]
arr = [ [1,2,3],[4,5,6,7] ]
ndim_matrix(arr)
#=> false
arr = [ [[1,2],[3,4]], [[5,6],[7,8]], [[9,10],[11,12]] ]
ndim_matrix(arr)
#=> [3,2,2]
arr = [ [[1,2],[3,4]], [[5,6],[7,8]], [[9,10]] ]
ndim_matrix(arr)
#=> false
arr = [ [[1,2],[3,4]], [[5,6,7],[7,8]], [[9,10],[11,12]] ]
ndim_matrix(arr)
#=> false
arr = [ [[[1,2,3],[2,1,3]],[[3,4,5],[4,3,2]]],
[[[5,6,7],[6,5,7]],[[7,8,9],[8,7,6]]],
[[[9,10,11],[10,9,8]],[[11,12,13],[12,11,10]]] ]
ndim_matrix(arr)
#=> [3, 2, 2, 3]
arr = [ [[[1,2,3],[2,1,3]],[[3,4],[4,3]]],
[[[5,6,7],[6,5,7]],[[7,8,9],[8,7,6]]],
[[[9,10,11],[10,9,8]],[[11,12,13],[12,11,10]]] ]
ndim_matrix(arr)
#=> false