Cara terbaik untuk mencetak hash dengan cantik

169

Saya memiliki hash besar dengan array dan hash bersarang. Saya hanya ingin mencetaknya sehingga 'dapat dibaca' oleh pengguna.

Saya ingin itu seperti to_yaml - itu cukup mudah dibaca - tapi masih terlalu teknologis.

Pada akhirnya akan menjadi pengguna akhir yang perlu membaca potongan data ini sehingga mereka perlu diformat dengan bersih.

Ada saran?

Adam O'Connor
sumber
kemungkinan duplikat dari Ruby: Cara membuat struktur cetak IRB untuk Array dan Hash
Martin Thoma
utilitas online jsonviewer.stack.hu . Namun itu tidak berfungsi dengan baik untuk sintaks roket hash.
Amit Patel

Jawaban:

256
require 'pp'
pp my_hash

Gunakan ppjika Anda membutuhkan solusi bawaan dan hanya ingin jeda baris yang masuk akal.

Gunakan awesome_print jika Anda dapat menginstal permata. (Tergantung pada pengguna Anda, Anda mungkin ingin menggunakan index:falseopsi untuk mematikan menampilkan indeks array.)

Phrogz
sumber
pp bagus, tetapi sangat disayangkan bahwa seseorang tidak dapat membatasi kedalaman.
akim
95

Jika Anda memiliki JSON, saya sarankan JSON.pretty_generate(hash)karena lebih sederhana daripada awesome_print , terlihat hebat di pretag, dan memungkinkan untuk menyalin dengan mudah dari halaman web. (Lihat juga: Bagaimana saya bisa "cantik" memformat output JSON saya di Ruby on Rails? )

David J.
sumber
Jawaban ini akan mendapat manfaat dari contoh aktual
Travis Bear
@ TravisBear Ada contoh keluaran jika Anda mengklik tautan "lihat juga" di jawaban saya. Saya merekomendasikan jawaban ini khususnya: stackoverflow.com/a/1823885/109618
David J.
8
Itu akanputs JSON.pretty_generate(hash)
joeloui
Jika Anda perlu membuat JSON, izinkan saya untuk merekomendasikan perpustakaan saya sendiri (gratis, OSS, tanpa iklan) untuk membuat JSON yang cantik dari Ruby atau JS: NeatJSON (Ruby) dan NeatJSON (Online / JS)
Phrogz
Maaf, saya menyadari sekarang bahwa pretty_generate tidak menerima objek Ruby, bukan teks json.
Tony
26

Solusi lain yang bekerja lebih baik untuk saya daripada ppatau awesome_print:

require 'pry' # must install the gem... but you ALWAYS want pry installed anyways
Pry::ColorPrinter.pp(obj)
Alex D
sumber
2
Perhatikan bahwa Pry::ColorPrinter.pp(obj)menulis ke standar keluar tetapi dapat mengambil params tambahan, termasuk tujuan. SepertiPry::ColorPrinter.pp(obj, a_logger)
Eric Urban
Saya terkejut ini tidak didokumentasikan dengan lebih baik: Saya selalu menggunakan pry sebagai konsol Rails saya, dan saya sudah lama mencari cara memanfaatkan printer cantiknya tanpa menggunakan permata lain. Terpilih karena solusi ini akhirnya mengakhiri pencarian panjang saya. :-)
wiz
20

Jika Anda tidak memiliki tindakan permata mewah, tetapi memiliki JSON, baris CLI ini akan berfungsi pada hash:

puts JSON.pretty_generate(my_hash).gsub(":", " =>")

#=>
{
  :key1 => "value1",

  :key2 => "value2",

  :key3 => "value3"
}
Nick Schwaderer
sumber
8
Diturunkan karena ini akan mengacaukan semua kunci dan nilai yang mengandung ":"
thomax
1
Ini juga tidak berurusan dengan null (JSON) vs nil (Ruby).
Rennex
1
Masih berguna untuk sebagian besar situasi.
Abram
1
Tidak bisa percaya ini tiga tahun kemudian! Terima kasih @Abram. :) Ini bukan solusi yang paling elegan di dunia tetapi menyelesaikan sesuatu dengan cepat.
Nick Schwaderer
4

Gunakan jawaban di atas jika Anda mencetak ke pengguna.

Jika Anda hanya ingin mencetaknya sendiri di konsol, saya sarankan menggunakan pry gem daripada irb. Selain pencetakan yang cantik, pry juga memiliki banyak fitur lainnya (lihat railscast di bawah)

permata instal mangsa

Dan periksa railscast ini:

http://railscasts.com/episodes/280-pry-with-rails

Abdo
sumber
3

Mudah dilakukan dengan json jika Anda percaya kunci Anda waras:

JSON.pretty_generate(a: 1, 2 => 3, 3 => nil).
  gsub(": null", ": nil").
  gsub(/(^\s*)"([a-zA-Z][a-zA-Z\d_]*)":/, "\\1\\2:"). # "foo": 1 -> foo: 1
  gsub(/(^\s*)(".*?"):/, "\\1\\2 =>") # "123": 1 -> "123" => 1

{
  a: 1,
  "2" => 3,
  "3" => nil
}
lebih kotor
sumber
1

Menggunakan Pry Anda hanya perlu menambahkan kode berikut ke ~ / .pryrc Anda:

require "awesome_print"
AwesomePrint.pry!
bartoindahouse
sumber
1

Dari semua permata yang saya coba, show_datapermata bekerja paling baik untuk saya, saya sekarang menggunakannya secara luas untuk mencatat hash params di Rails hampir sepanjang waktu

Dr.Strangelove
sumber
0

Untuk hash bersarang besar, skrip ini bisa membantu Anda. Ini mencetak hash bersarang dalam sintaks python bagus / seperti dengan hanya indentasi untuk membuatnya mudah untuk menyalin.

module PrettyHash
  # Usage: PrettyHash.call(nested_hash)
  # Prints the nested hash in the easy to look on format
  # Returns the amount of all values in the nested hash

  def self.call(hash, level: 0, indent: 2)
    unique_values_count = 0
    hash.each do |k, v|
      (level * indent).times { print ' ' }
      print "#{k}:"
      if v.is_a?(Hash)
        puts
        unique_values_count += call(v, level: level + 1, indent: indent)
      else
        puts " #{v}"
        unique_values_count += 1
      end
    end
    unique_values_count
  end
end

Contoh penggunaan:

  h = {a: { b: { c: :d }, e: :f }, g: :i }
  PrettyHash.call(h)

a:
  b:
    c: d
  e: f
g: i
=> 3

Nilai yang dikembalikan adalah hitungan (3) dari semua nilai tingkat akhir hash bersarang.

swilgosz
sumber
0

Berikut ini pendekatan lain menggunakan json and rouge:

require 'json'
require 'rouge'

formatter = Rouge::Formatters::Terminal256.new
json_lexer = Rouge::Lexers::JSON.new

puts formatter.format(json_lexer.lex(JSON.pretty_generate(JSON.parse(response))))

(respons parses dari misalnya RestClient)

Adobe
sumber
0

Di Rails

Jika Anda perlu

  • Hash "cukup dicetak"
  • di mis. Rails.logger
  • itu, secara khusus, berjalan inspect pada objek di Hash
    • yang berguna jika Anda mengganti / mendefinisikan inspectmetode di objek Anda seperti yang seharusnya

... maka ini bekerja dengan baik! (Dan semakin baik, semakin besar dan semakin bersarang objek Hash Anda.)

logger.error my_hash.pretty_inspect

Sebagai contoh:

class MyObject1
  def inspect
    "<#{'*' * 10} My Object 1 #{'*' * 10}>"
  end
end

class MyObject2
  def inspect
    "<#{'*' * 10} My Object 2 #{'*' * 10}>"
  end
end

my_hash = { a: 1, b: MyObject1.new, MyObject2.new => 3 }

Rails.logger.error my_hash
# {:a=>1, :b=><********** My Object 1 **********>, <********** My Object 2 **********>=>3}

# EW! ^

Rails.logger.error my_hash.pretty_inspect
# {:a=>1,
#  :b=><********** My Object 1 **********>,
#  <********** My Object 2 **********>=>3}

pretty_inspect berasal dari PrettyPrint , yang termasuk rail secara default. Jadi, tidak perlu permata dan tidak perlu konversi ke JSON.

Tidak di rel

Jika Anda tidak berada di Rails atau jika hal di atas gagal karena suatu alasan, coba gunakan require "pp"terlebih dahulu. Sebagai contoh:

require "pp"  # <-----------

class MyObject1
  def inspect
    "<#{'*' * 10} My Object 1 #{'*' * 10}>"
  end
end

class MyObject2
  def inspect
    "<#{'*' * 10} My Object 2 #{'*' * 10}>"
  end
end

my_hash = { a: 1, b: MyObject1.new, MyObject2.new => 3 }

puts my_hash
# {:a=>1, :b=><********** My Object 1 **********>, <********** My Object 2 **********>=>3}

# EW! ^

puts my_hash.pretty_inspect
# {:a=>1,
#  :b=><********** My Object 1 **********>,
#  <********** My Object 2 **********>=>3}

Contoh Lengkap

Big ol' pretty_inspected Hash contoh dari proyek saya dengan teks proyek-spesifik dari objek Diperiksa saya disunting:

{<***::******************[**:****, ************************:****]********* * ****** ******************** **** :: *********** - *** ******* *********>=>
  {:errors=>
    ["************ ************ ********** ***** ****** ******** ***** ****** ******** **** ********** **** ***** ***** ******* ******",
     "************ ************ ********** ***** ****** ******** ***** ****** ******** **** ********** is invalid",
     "************ ************ ********** ***** ****** ******** is invalid",
     "************ ************ ********** is invalid",
     "************ ************ is invalid",
     "************ is invalid"],
   :************=>
    [{<***::**********[**:****, *************:**, ******************:*, ***********************:****] :: **** **** ****>=>
       {:************=>
         [{<***::***********[**:*****, *************:****, *******************:**]******* :: *** - ******* ***** - *>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:**]******* :: *** - *>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:**]******* :: ********* - *>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:**]******* :: ********** - ********** *>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:**]******* :: ******** - *>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:**]******* :: **** - *******>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:**]******* :: *** - ********** ***** - *>=>
            {}}]}},
     {<***::**********[**:****, *************:**, ******************:*, ***********************:****] ******************** :: *** - *****>=>
       {:errors=>
         ["************ ********** ***** ****** ******** ***** ****** ******** **** ********** **** ***** ***** ******* ******",
          "************ ********** ***** ****** ******** ***** ****** ******** **** ********** is invalid",
          "************ ********** ***** ****** ******** is invalid",
          "************ ********** is invalid",
          "************ is invalid"],
        :************=>
         [{<***::***********[**:*****, *************:****, *******************:***]******* :: ****** - ** - ********>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:***]******* :: ****** - ** - ********>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:**]******* :: ****** - ** - *******>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:**]*********** :: ****>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:**]******* :: ****** - ** - *******>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:**]******* :: ****** - ** - *********>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:**]******* :: ****** - ** - *******>=>
            {:errors=>
              ["********** ***** ****** ******** ***** ****** ******** **** ********** **** ***** ***** ******* ******",
               "********** ***** ****** ******** ***** ****** ******** **** ********** is invalid",
               "********** ***** ****** ******** is invalid",
               "********** is invalid"],
             :**********************=>
              [{<***::*******************[**:******, ************************:***]****-************ ******************** ***: * :: *** - ***** * ****** ** - ******* * **: *******>=>
                 {:errors=>
                   ["***** ****** ******** **** ********** **** ***** ***** ******* ******",
                    "***** ****** ******** **** ********** is invalid"],
                  :***************=>
                   [{<***::********************************[**:******, *************:******, ***********:******, ***********:"************ ************"]** * *** * ****-******* * ******** * ********* ******************** *********************: ***** :: "**** *" -> "">=>
                      {:errors=>["**** ***** ***** ******* ******"],
                       :**********=>
                        {<***::*****************[**:******, ****************:["****** ***", "****** ***", "****** ****", "******* ***", "******* ****", "******* ***", "****"], **:""] :: "**** *" -> "">=>
                          {:errors=>
                            ["***** ******* ******",
                             "***** ******* ******"]}}}}]}}]}},
          {<***::***********[**:*****, *************:****, *******************:**]******* :: ****** - ** - *********>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:**]******* :: ****** - ** - *********>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:***]******* :: ****** - ** - ********>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:***]******* :: ****** - ** - **********>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:***]******* :: ****** - ** - **********>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:***]******* :: ****** - ** - **********>=>
            {}}]}}]}}
pdobb
sumber
-4

Di bawah Rails, array dan hash di Ruby memiliki fungsi to_json bawaan. Saya akan menggunakan JSON hanya karena sangat mudah dibaca dalam browser web, misalnya Google Chrome.

Yang sedang berkata jika Anda khawatir tentang hal itu tampak terlalu "terlihat tech" Anda mungkin harus menulis fungsi Anda sendiri yang menggantikan kurung kurawal dan kurung kurawal di hash dan array dengan white-space dan karakter lainnya.

Cari fungsi gsub untuk cara yang sangat baik untuk melakukannya. Terus bermain-main dengan karakter yang berbeda dan jumlah spasi yang berbeda hingga Anda menemukan sesuatu yang terlihat menarik. http://ruby-doc.org/core-1.9.3/String.html#method-i-gsub

Sid
sumber
7
Array dan hash tidak memiliki metode to_json bawaan, ini ditambahkan oleh ActiveSupport dari Rails.
Tom De Leu
Ini bahkan lebih buruk dari normal biasanya:{"programming_language":{"ruby":{},"python":{}}}
Darek Nędza
OP tidak mengesampingkan Rails
Will Sheppard