新手问题 如何初始化一个二维数组?

lgn21st · 2012年09月19日 · 最后由 alvin2ye 回复于 2015年08月15日 · 15822 次阅读

我需要快速初始化一个任意的二维数组,比如:

[
  [0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0]
]

问:什么样的 Ruby 代码,初始化这样一个数组最简单?

这样? Array.new(8, Array.new(8, 0))

require 'matrix'
m = Matrix.build(8, 8){0}.to_a

[Array.new(8, 0)] * 8

require 'matrix'
m = Matrix.zero(8).to_a

之前的 Matrix.build 在 1.8 还没有.

#1 楼 @yesmeck 这个做法有个问题

>> arr = Array.new(8, Array.new(8, 0))
=> [[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]]
>> arr[0][0] = 1
=> 1
>> arr
=> [[1, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0]]

用 Array.new 创建的这个对象去填充,造成的结果是修改一个数值,所有的内部数组都会被修改。

额。。看来要这样 array = Array.new(8) { Array.new(8, 0) }

我觉得 LZ 的方法就不错...

#2 楼 @5long #4 楼 @5long Matrix 对象如此神奇,受教。有没有一种不借助外部 lib 的方法?

#6 楼 @yesmeck 正解,刚刚好我今天遇到这样一个需求,在网上找到了这个 http://rubyquicktips.com/post/844746058/how-to-initialize-a-multidimensional-array

顺便推荐这个网站: http://rubyquicktips.com/

#8 楼 @lgn21st

row, col, val = 8, 8, 0
Array.new(row * col){val}.each_slice(col).to_a

免去变量助记, 也是一行.

#10 楼 @5long Cool,就是可读性稍微弱一点。

eval ([[0] * 8] * 8).to_s

#12 楼 @jjym 果然 Ruby 程序员的思维很跳跃~ 赞!

等出车票空又想了一个.. 8.times.map{8.times.map{0}}

#14 楼 @jjym 不怕你笑话,我第一次写成这样:

arr = []
0.upto(7) do |i|
  arr[i] = []
  0.upto(7) do |j|
    arr[i][j] = 0
  end
end

#15 楼 @lgn21st 以前写 C# 就这样..还要多几行 rubyAPI 博大精深啊..

Array.new(8) {Array.new(8, 0)} 好像我之前问过你这个问题,不知道是不是现在的 API 注释清楚了。

new(size=0, obj=nil) new(array) new(size) {|index| block }

Returns a new array. In the first form, the new array is empty. In the second it is created with size copies of obj (that is, size references to the same obj). The third form creates a copy of the array passed as a parameter (the array is generated by calling #to_ary on the parameter). In the last form, an array of the given size is created. Each element in this array is calculated by passing the element’s index to the given block and storing the return value.

Array.new(8) {[0]*8}

哎呀,写完才发现 ls 已经贴出文档了。。。

@jjym 上次在群里战过了 对枚举器做 map 不科学啊 而且会做一个隐式的 to_a map 和 reduce 都是对 vector 的操作 应该写成 ([0]*8).map {[0]*8} 而且内部没必要再 map 了,因为 Fixnum Fixnum objects have immediate value. This means that when they are assigned or passed as parameters, the actual object is passed, rather than a reference to that object.

@lgn21st ([0]*8).map {[0]*8} 这种写法比 Array.new(8) {[0]*8} 少打一个字。。。

Array.new(64, 0).in_groups_of(8) ActiveSupport的扩展方法

#19 楼 @jasl 其实你这 [0] * 8 和 to_a 差不多了已经..

@jjym 就是为了 to_a 啊 但别忘了 8.times.to_a 是先创建枚举器再 to_a 多一步

我先想到的是

8.times.map{ [0] * 8 }

#11 楼 @lgn21st 我还真觉得直接来不错, 一目了然 可读性最强

[ [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0] ]

#25 楼 @knwang 我希望初始化任意一个二位数组,而不是固定二维数组。

#26 楼 @lgn21st 用 IDE,写个模板生成,估计能行

#23 楼 @jasl 差不多的。。你这也是先建立 [0] 再建立 [0,...] 的,一共俩数组

做马桶的时候想想

[[0]* 8] * 8

可读性好又短

#29 楼 @alvin2ye 貌似你这个从可读性上已经无敌了 😄

我也来提供一个:

([0]*64).each_slice(8).to_a

#29 楼 @alvin2ye

irb(main):001:0> a = [[0]*8]*8
=> [[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]]
irb(main):002:0> a[0][0] = 1
=> 1
irb(main):003:0> a 
=> [[1, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0]]

要让这个工作起来也不短了

([[0]*8]*8).map!(&:dup)

#32 楼 @bhuztez

8.times.map{ [0] * 8 } 正常,可读性还行

@alvin2ye 这是在战数学概念~ 不是可读性的问题

#37 楼 @fsword @alvin2ye 那个是错的,为何无敌呢:)

#38 楼 @ashchan 的确是错的,只是看起来无敌,呵呵。

#38 楼 @ashchan 恩?哪里错了,我还没看出来?

#40 楼 @fsword 看 33 楼 或者在 irb 里运行:

irb > ([[0]*8]*8).map(&:object_id)

#41 楼 @doitian 明白了,k,被羞辱了

Array.new(8,1).zip *[Array.new(8,0)]*8

ruby'有群坏人玩弄你~~

0.upto(8).map { Array.new(8, 0) }
#Or
0.upto(8).map {[0]*8}

只要用迭代器就好。

(0..8).map { [0]*8 }

#14 楼 @jjym 这个很棒啊。。 而且没有错。。

#49 楼 @sawater 这个是错的,请看 32 楼 这个可以

8.times.map{ [0] * 8 }

#9 楼 @lgn21st 确实 这种方式在 当使用 单个赋值时更好

#29 楼 @alvin2ye 根本就是错的。 这个是浅复制。

Fixnum 还有浅复制?

需要 登录 后方可回复, 如果你还没有账号请 注册新账号