2

Unixの''ls'コマンドのデフォルト出力と同じように(少なくともOS Xでは)列に出力したい大きなRuby配列があります。これを行うことができるgemまたは組み込みのメソッドはありますか?私はawesome_printgemを知っています。セクシーな出力がありますが、列を提供していないようです。

4

5 に答える 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

コメント投稿者のショーンに同意しますが、mysefを保持できず、代わりにおしっこを保持してこのかわい子ちゃんに負担をかけました。私は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 に答える
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 に答える
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のソリューションのいくつかの改善:

  1. 呼び出し元が配列の配列でない場合は、例外を発生させます。
  2. 型キャストして任意の値を文字列に変換すると、文字列と数値が混在する配列で機能します。
  3. 任意の列区切り文字列を引数として指定できます。
  4. 出力はテーブルとしてフォーマットされた文字列であるため、さらに処理でき、出力が予期されていない場合でも何も壊れません。
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 に答える