我有一个大型 Ruby 数组,我想在列中打印,就像 Unix' 'ls' 命令的默认输出(至少在 OS X 上)。是否有可以做到这一点的 gem 或内置方法?我知道 awesome_print gem。它有一些性感的输出,但似乎没有提供列。
问问题
1003 次
5 回答
7
Enumerable#each_slice可能是你的朋友。
$ irb
irb> a = (0..18).to_a
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
irb> a.each_slice(5) { |row| puts row.map{|e| "%5d" % e}.join(" ") }
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18
如果您希望它们在列中排序,您可以使用 slice 和Enumerable#zip
irb> cols = a.each_slice((a.size+2)/3).to_a
=> [[0, 1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12, 13], [14, 15, 16, 17, 18]]
irb> cols.first.zip( *cols[1..-1] ).each{|row| puts row.map{|e| e ? '%5d' % e : ' '}.join(" ") }
0 7 14
1 8 15
2 9 16
3 10 17
4 11 18
5 12
6 13
于 2012-06-19T20:29:14.380 回答
1
除了我的第一个完整的可配置解决方案之外,还有一个基于元素最大字符串长度的更短的解决方案
class Array
def to_table l = []
self.each{|r|r.each_with_index{|f,i|l[i] = [l[i]||0, f.length].max}}
self.each{|r|r.each_with_index{|f,i|print "#{f.ljust l[i]}|"};puts ""}
end
end
[["on", "two", "three", "a loooooooooooooooonger field"],["four","five","looooooooooonger","short one"]].to_table
给
on |two |three |a loooooooooooooooonger field|
four|five|looooooooooonger|short one |
于 2012-06-19T22:39:36.430 回答
1
我同意评论者 Sean 的观点,但我只是无法控制自己,而是抱着我的小便来给这个可爱的小便,我在 Windows 上,所以不知道 ls 的输出是如何相似的,但我相信有足够的选择在这里为您提供所需的输出
cm = {'headers' => ['first', 'second', 'third', 'fourth'], 'width' => [5, 5, 16, 30], 'separator' => '|', 'align' => [:left,:right,:left,:right]}
a = [["on", "two", "three", "a loooooooooooooooonger field"],["four","five","looooooooooonger","short one"]]
cm['headers'].each_with_index{|header, index|w = cm['width'][index];print "#{cm['align'][index]==:left ? header.ljust(w)[0..w-1]:header.rjust(w)[0..w-1]}#{cm['separator']}"}
puts ""
a.each do |record|
record.each_with_index do |field, index|
w = cm['width'][index]
print "#{cm['align'][index]==:left ? field.ljust(w)[0..w-1]:field.rjust(w)[0..w-1]}#{cm['separator']}"
end
puts ""
end
给
first|secon|third | fourth|
on | two|three | a loooooooooooooooonger field|
four | five|looooooooooonger| short one|
于 2012-06-19T20:55:32.540 回答
0
我认为使用hirb
更有用:
require 'hirb'
Hirb.enable :output=>{"Array"=>{:class=>Hirb::Helpers::Table}} #=> true
[[1,2], [2,3]]
+---+---+
| 0 | 1 |
+---+---+
| 1 | 2 |
| 2 | 3 |
+---+---+
2 rows in set
[[5,6,3,4]]
+---+---+---+---+
| 0 | 1 | 2 | 3 |
+---+---+---+---+
| 5 | 6 | 3 | 4 |
+---+---+---+---+
1 row in set
于 2012-06-19T20:53:32.307 回答
0
@peter 解决方案的一些改进:
- 如果调用者不是数组数组,则引发异常;
- 类型转换为字符串任何值都将适用于包含字符串和数字混合的数组;
- 任何列分隔符字符串都可以指定为参数;
- 输出是一个格式化为表格的字符串,因此可以进一步处理它,并且如果不需要输出,也不会破坏任何内容。
class Array
# Convert an Array of arrays into a String, formatted as a table.
def columnize(sep=" ")
each{|r| r.is_a? Array or raise NoMethodError, "Must be called on an Array of arrays."}
s = ""
l = []
each{|r|r.each_with_index{|f,i| l[i] = [l[i]||0, f.to_s.length].max}}
each{|r|r.each_with_index{|f,i| s << "#{f.to_s.ljust l[i]}#{sep}"}; s << "\n"}
return s
end
end
称为
puts [["field", 2, 3, "another field"],[4,5,"looooooooooonger","short one"]].columnize(" | ")
产生这个输出
field | 2 | 3 | another field |
4 | 5 | looooooooooonger | short one |
于 2021-10-14T17:42:59.793 回答