我想知道是否有可能创建二维数组并快速访问其中的任何水平或垂直子数组?
我相信在以下情况下我们可以访问水平子数组:
x = Array.new(10) { Array.new(20) }
x[6][3..8] = 'something'
但是据我了解,我们无法像这样访问它:
x[3..8][6]
我该如何避免或破解此限制?
Answers:
二维Arrays
实现方式存在一些问题。
a= [[1,2],[3,4]]
a[0][2]= 5 # works
a[2][0]= 6 # error
Hash
如 Array
我更喜欢Hashes
用于多维Arrays
a= Hash.new
a[[1,2]]= 23
a[[5,6]]= 42
这样的好处是,您不必手动创建列或行。插入哈希值几乎是O(1),因此这里没有缺点,只要您的值Hash
不会太大即可。
您甚至可以为所有未指定的元素设置默认值
a= Hash.new(0)
所以现在关于如何获取子数组
(3..5).to_a.product([2]).collect { |index| a[index] }
[2].product((3..5).to_a).collect { |index| a[index] }
(a..b).to_a
在O(n)中运行。从中检索元素Hash
几乎为O(1),因此收集操作几乎为O(n)。没有办法使其比O(n)更快,因为复制n个元素始终为O(n)。
Hashes
太大时可能会有问题。因此Array
,如果我知道我的数据量越来越大,那么我将三思而后行地实现这种多维。
a[2][0]
因为尚未创建第三个元素而出现错误?有意义a[1][0]=6
吗?我知道这已经很老了……刚才正在看Ruby。
a[1][0] = 6
可以正常工作。您可以使用a [2]创建第三行,但是直到创建后才能对其进行索引。例如,a[2] = []
随后a[2][0] = 6
将工作。
almost O(1)
[...]表示什么?
您没有说明您的实际目标,但这可能会有所帮助:
require 'matrix' # bundled with Ruby
m = Matrix[
[1, 2, 3],
[4, 5, 6]
]
m.column(0) # ==> Vector[1, 4]
(向量的作用类似于数组)
或者,根据需要使用类似的符号:
m.minor(0..1, 2..2) # => Matrix[[3], [6]]
x[6][3..8]
符号,则可以始终Matrix
对它进行子类化和扩展。
Matrix
阅读此答案后,我开始使用它,这很棒。但是,有一个很大的限制,那就是在移动之前最好牢记Matrix
-它们是不可变的。因此,没有办法修改单个元素,即m(0, 0) = 0 # => error
Matrix
。至于它们的不变性,我不会称其为限制,而是一个功能。显然,马克·安雷(Marc-Anré)不仅使自己的生活更轻松,而且还以数字的概括形式表示矩阵。
OpenMatrix
例如likeOpenStruct
和Struct
),或者确保用户首先必须执行诸如Matrix#open
or#unlock
或what的操作。
x.transpose[6][3..8]
要么 x[3..8].map {|r| r [6]}
会给你想要的。
例:
a = [ [1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 15],
[21, 22, 23, 24, 25]
]
#a[1..2][2] -> [8,13]
puts a.transpose[2][1..2].inspect # [8,13]
puts a[1..2].map {|r| r[2]}.inspect # [8,13]
transpose
吗?大!
collect
而不是map
添加一些清晰度。
我很确定这很简单
2.0.0p247 :032 > list = Array.new(5)
=> [nil, nil, nil, nil, nil]
2.0.0p247 :033 > list.map!{ |x| x = [0] }
=> [[0], [0], [0], [0], [0]]
2.0.0p247 :034 > list[0][0]
=> 0
x
,[0]
无论如何都会返回
Array.new
可以直接使用一个块,不需要map
:Array.new(5) {|x| x = [0] }
=> [[0], [0], [0], [0], [0]]
甚至更简单:Array.new(5,[0])
=> [[0], [0], [0], [0], [0]]
x[3..8].each{|a|a[6] = 'something'}
这对你来说很丑。