0

I know my question is pretty simple, but I can't manage to find an answer on the internet.

I have a hash called sorted_frequency. I want to output it as a table using the gem hirb. At the time I just have been able to print the hash under the default field names (0, 1). So it looks like that:

0      1

wordA  ntimes
wordB  mtimes
wordC  rtimes

I'd like to rename the field names so it would be something like this:

words  number of times

wordA  ntimes
wordB  mtimes
wordC  rtimes

My actual code is this:

#needs to install 'docx' and 'hirb' gems

require 'docx'
require 'hirb'
doc = Docx::Document.open('monografia.docx')
text_listed = doc.to_s.downcase.split(" ")
forbidden_list = ["o", "si", "em", "ha", "no", "és", "amb", "i", "/","el", 
"la", "els","les", "l'", "lo", "los", "en", "n'", "na", "es", "ets", "s'", 
"sa", "so", "ses", "sos", "un", "una", "unes", "uns", "a", "que", "s'", 
"al", "de","del", "per", "ens", "als", "com"]

clean_text= text_listed - forbidden_list

frequency = Hash.new 0

clean_text.each { |word| frequency[word] += 1 }

sorted_frequency = Hash[frequency.sort_by{ | word, times | -times }[0..20]]

puts Hirb::Helpers::AutoTable.render(sorted_frequency)

Again, I'm sorry if this a newbie question

EDIT:

As all my code has been asked, I'll explain it. It opens a docx document with the help of a gem called 'docx'. After that, it splits the doc by spaces and creates an array. After that, I remove some words I don't want to count (those included in the forbidden_list). Then I create a hash where the key is the word, and the value is the number of times that word appears in the docx. After that, I sort that hash and output using the gem 'hirb. The problem is I just don't know how to name the fields of the table created. I hope someone can help me.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
H4ml3tt3d
  • 21
  • 3
  • So you thought it would be enlightening if you didn't post the value of `sorted_frequency`? – 7stud Jan 28 '18 at 16:38
  • I think it's obvious the hash is first => second; third => fourth; fifth => sixth. What's the deal with that? – H4ml3tt3d Jan 28 '18 at 18:23
  • *I think it's obvious the hash is* -- Why do you think that? – 7stud Jan 28 '18 at 18:42
  • Because it is the output I pasted in the original question. Again, what's the deal with this? I thought it would be irrellevant to explicit the values of the hash. I assume it's a simple hash with values associated to a unique key... – H4ml3tt3d Jan 28 '18 at 18:46
  • *Again, what's the deal with this?* Besides the fact that you misspelled `hirb` in your actual code? And you make people try to guess what your starting data is? When you ask a question on a computer programming forum, you need to post a working example that demonstrates your problem. You need to post the example code and the actual results and state your expected results and post any errors. Code in the form of a twitter style message is not appropriate on a technical forum. OKAY?! – 7stud Jan 28 '18 at 19:13
  • I already posted the code. I hope I can get some help. – H4ml3tt3d Jan 28 '18 at 19:33

1 Answers1

0

According to the hirb docs, AutoTable.render() takes an argument which can be an array_of_arrays or an array_of_hashes. But because your hash argument worked, I looked at your table output, and I decided to try to merely add an option to change the column names that you got:

require 'hirb'

freqs = {
  'go' => 3,
  'no' => 4,
  'to' => 1
}

puts Hirb::Helpers::AutoTable.render(
  freqs,
  fields: [1, 0],  #Specify which fields to include in the table and their order. 
                   #For a row that is an array, the field names are the integers 0, 1, 2, etc.
                   #For a row that is a hash, the field names are the keys.
  headers: {0 => 'Word', 1 => 'Frequency'},  #Convert the field names to something more desirable for the column headers
  description: false #Get rid of "3 rows in set" following the table
)


--output:--
+-----------+------+
| Frequency | Word |
+-----------+------+
| 3         | go   |
| 4         | no   |
| 1         | to   |
+-----------+------+

It worked. What must be happening is: AutoTable.render() expects an array--either an array_of_arrays or an array_of_hashes--and if the method doesn't get an array as an argument, it calls to_a() on the argument. Take a look at what happens to your hash:

~/ruby_programs$ irb
2.4.0 :001 > freqs = {'go' => 3, 'no' => 4, 'to' => 1}
 => {"go"=>3, "no"=>4, "to"=>1} 

2.4.0 :002 > freqs.to_a
 => [["go", 3], ["no", 4], ["to", 1]] 

There's the array_of_arrays that AutoTable.render() needs. Rearranging a little, the array_of_arrays looks like this:

index 0  index 1
     |    |
[    V    V
   ["go", 3],  #row array
   ["no", 4], 
   ["to", 1]
] 

For an array_of_arrays, the column headers in the table are the index positions in each row array. The options for AutoTable.render() let you specify which columns/index positions to include in the table and their order, and the options allow you to convert the column headers to something more desirable.

Here's a more general example:

require 'hirb'
require 'pp'

data = [
  ['go', 1, '1/12/18'],
  ['to', 4, '1/24/18'],
  ['at', 2, '1/28/18']
]

puts Hirb::Helpers::AutoTable.render(
  data,
  fields: [2, 0],  #Specify the index positions in each row array to include in the table and their column order in the table
  headers: {0 => 'Word', 2 => 'Date'},  #Convert the column headers to something more desirable
  description: false #Get rid of "3 rows in set" following the table
)

--output:--
+---------+------+
| Date    | Word |
+---------+------+
| 1/12/18 | go   |
| 1/24/18 | to   |
| 1/28/18 | at   |
+---------+------+

====

require 'hirb'
require 'pp'

freqs = {
  'go' => 3,
  'no' => 4,
  'to' => 1
}

col_names = %w[word count]

new_freqs = freqs.map do |key, val| 
  {col_names[0] => key, col_names[1] => val}
end

pp new_freqs

puts Hirb::Helpers::AutoTable.render(
  new_freqs, 
  fields: ['word', 'count'],  #Specify which keys to include in table and their column order.
  headers: {'word' => 'Good Word', 'count' => 'Frequency'},  #Convert keys to more desirable headers.
  description: false #Get rid of "3 rows in set" following the table
)

--output:--
[{"word"=>"go", "count"=>3},
 {"word"=>"no", "count"=>4},
 {"word"=>"to", "count"=>1}]
+-----------+-----------+
| Good Word | Frequency |
+-----------+-----------+
| go        | 3         |
| no        | 4         |
| to        | 1         |
+-----------+-----------+

====

require 'hirb'
require 'pp'

freqs = {
  'go' => 3,
  'no' => 4,
  'to' => 1
}

col_names = %i[word count]

new_freqs = freqs.map do |key, val| 
  {col_names[0] => key, col_names[1] => val}
end

pp new_freqs
puts Hirb::Helpers::AutoTable.render(new_freqs)

--output:--
[{:word=>"go", :count=>3}, {:word=>"no", :count=>4}, {:word=>"to", :count=>1}]
+-------+------+
| count | word |
+-------+------+
| 3     | go   |
| 4     | no   |
| 1     | to   |
+-------+------+
3 rows in set

===

require 'hirb'
require 'pp'

data = {
  'first' => 'second', 
  'third' => 'fourth', 
  'fifth' => 'sixth'
}

col_names = %i[field1 field2]

new_data = data.map do |key, val| 
  {col_names[0] => key, col_names[1] => val}
end

pp new_data
puts Hirb::Helpers::AutoTable.render(new_data)

--output:--
[{:field1=>"first", :field2=>"second"},
 {:field1=>"third", :field2=>"fourth"},
 {:field1=>"fifth", :field2=>"sixth"}]
+--------+--------+
| field1 | field2 |
+--------+--------+
| first  | second |
| third  | fourth |
| fifth  | sixth  |
+--------+--------+
3 rows in set

=====

require 'hirb'

data = [
  {field1: 'first', field2: 'second'},
  {field1: 'third', field2: 'fourth'},
  {field1: 'fifth', field2: 'sixth'}
]

puts Hirb::Helpers::AutoTable.render(data)

--output:--
+--------+--------+
| field1 | field2 |
+--------+--------+
| first  | second |
| third  | fourth |
| fifth  | sixth  |
+--------+--------+
3 rows in set
7stud
  • 46,922
  • 14
  • 101
  • 127
  • Can you explain it to me? I thought the solution would be some explanation on the hirb syntax. – H4ml3tt3d Jan 28 '18 at 20:15
  • @H4ml3tt3d, The `AutoTable.render()` method takes an array of arrays or an array of hashes--not a hash. So the answer converts your data to an array of hashes--as shown in the output. – 7stud Jan 28 '18 at 20:58
  • @H4ml3tt3d, Ah. No need to manually convert your data--`render()` will do it for you. You get the syntax explanation that you wanted. – 7stud Jan 28 '18 at 22:04
  • I couldn't check it earlier. The information you provided to me is just fantastic, the code works perfectly. Thank you for your effort and your time :) – H4ml3tt3d Jan 31 '18 at 15:49