如何显示每个嵌套ruby的数组?

时间:2016-09-03 00:13:14

标签: ruby

给定一个数组列表,我想以二数组的形式显示数组的所有对组合。例如,假设我有一个[1,2,3]数组。

[1, 1]
[1, 2]
[1, 3]
[2, 1]
[2, 2]
[2, 3]
[3, 1]
[3, 2]
[3, 3]

预期结果

这是我提出的功能:

def all_combination(list)
  list.each do |i|
    list.each do |j|
      puts [i,j]
    end
  end
end

arr1 = [1,2,3] #arr1 can be an array of any size. It will always be integer.
all_combination(arr1)

但是,当我执行上面的代码时,会显示

1
1
1
2
1
3
...

我的基本红宝石知识似乎存在差距。 为什么 puts [i,j]不起作用?如何使其显示实际数组,如预期结果部分所示?

我可以使用puts "#{i}, #{j}",但它不会返回数组[a,b]

3 个答案:

答案 0 :(得分:1)

有一种内置的方法可以满足您的需求:

"+"

如果您希望坚持使用自己的方法(与自己一起获得“配对”项目),请将[1,2,3].permutation(2).each {|a| p a} 更改为puts [i,j]p [i,j] - puts [i,j].to_s使用字符串。

答案 1 :(得分:0)

您获取每个新行的数据的原因是因为puts将给定的每个对象写入新行。 Here是关于此的文档:

  

将给定对象写入ios,与IO#print一样。写一条记录   在任何尚未结束的分隔符之后的分隔符(通常是换行符)   换行序列。如果使用数组参数调用,则写入每个参数   新行上的元素。如果不带参数调用,则输出一个   记录分隔符。

如果Array#permutation做了你想做的事情,那么,我认为它不符合你的要求(即[1,1],[2,2],[3] ,3]将不包括在内。)

以下内容应该为您提供您最初要求的内容。

def all_combination(list)
  a = []
  list.each do |i|
    list.each do |j|
      a << [i,j]
    end
  end
  a
end

x = all_combination [1,2,3]
p x
puts x

=> [[1, 1], [1, 2], [1, 3], [2, 1], [2, 2], [2, 3], [3, 1], [3, 2], [3, 3]]
1
1
1
2
1
3
2
1
2
2
2
3
3
1
3
2
3
3

x是您要查找的返回值,如p x

所示

ps:这可能是用一条线来完成的,或者使用Array#reduce来做得太少,但这是相当紧张的。

答案 2 :(得分:0)

  

我的基本红宝石知识似乎存在差距。 为什么 puts [i,j]不起作用?

为什么我们不看文档?

The documentation for Kernel#puts只是将我们引用到IO#puts的文档:

  

puts(obj, …)nil

     

相当于

$stdout.puts(obj, …)

The documentation for IO#puts说这个(粗体强调我的):

  

puts(obj, …)nil

     

将给定对象与IO#print一样写入 ios 。在没有以换行符结束的任何内容之后写入记录分隔符(通常是换行符)。 如果使用数组参数调用,则将每个元素写入新行。如果不带参数调用,则输出单个记录分隔符。

正如您所看到的,文档清楚地指出,当您将Array传递给puts时,它会在单独的行上打印每个元素。

  

如何让它显示实际数组,就像它在预期结果部分中显示的那样?

您无法显示“实际数组”。数组是将索引映射到对象的数据结构。这是个主意。你无法展示自己的想法。您只能显示文字(即String)。因此,您需要构建一个看似所需输出的String

  

我可以使用puts "#{i}, #{j}",但它不会返回数组[a,b]

嗯,它不打印括号,因为你没有告诉它打印括号。它只会打印您的String,但String中没有任何括号,因此输出中不会有括号。你只需要添加它们:

puts "[#{i}, #{j}]"

注意:您可能会想要使用Array#inspectArray#to_sKernel#p,但请不要:他们的输出格式保证。你可能会得到你所期望的,但是你可能不会。

#inspect用于人类可读的调试输出。 Kernel#p只需拨打#inspect即可。在Array#to_s的特定情况下,它只是Array#inspect的别名,文档只说:

  

inspectstring

     

to_sstring

     

创建self的字符串表示形式。

[ "a", "b", "c" ].to_s     #=> "[\"a\", \"b\", \"c\"]"

请注意,它仅显示“ a 字符串表示形式”,但不保证返回的字符串表示形式。

I 解决问题的方式是这样的:

def all_combination(list)
  list.product(list).map {|a, b| "[#{a}, #{b}]" }
end

arr1 = [1,2,3]
puts all_combination(arr1)

我主要做了两件事:

  • 使用Ruby核心库(Array#productEnumerable#map)已提供的更高级别的集合操作。这降低了理解解决方案的认知开销。它现在只是一行清楚地告诉你它做了什么:首先用自己生成列表的笛卡尔积,然后将每对转换为合适的字符串表示。
  • 将输出与打印输出分开构造。这样可以更容易测试:您可以简单地断言返回正确的值,而不是直接打印到屏幕上,然后跳过箍来捕获屏幕输出并将其与一些预先录制的屏幕输出或类似的东西进行比较这一点。

但仍有待改进的地方:

  • 该方法做了两件事:生成笛卡尔积并将其转换为字符串表示
  • 方法命名:这实际上暗示了上面的#1:当方法一次做多个事情时,你如何找到一个合适的名称来准确描述一个方法的作用?