class LineAnalyzer
##highest_wf_count=[]
##highest_wf_words=[]
attr_accessor :highest_wf_count ,:highest_wf_words ,:content , :line_number
def initialize(line,num)
#content=line
#line_number=num
calculate_word_frequency(#content,#line_number).call
end
def calculate_word_frequency(con,num)
#content,#line_number=con,num
#arr= #content.split()
#arr.map do |txt|
#count=0
#i=0
while #i<#content.length
#count+=1 if txt.eql?(#arr[#i])
#i+=1
end
##highest_wf_count[#line_number]= #count
##highest_wf_words[#line_number]= txt
#arr.delete(txt)
end
end
end
class Solution < LineAnalyzer
attr_accessor :analyzers, :highest_count_across_lines, :highest_count_words_across_lines
def initialize
#analyzer=[]
#highest_count_across_lines=0
#highest_count_words_across_lines=[]
end
def analyze_file()
#arr=IO.readlines(ARGV[0])
#analyzers=Array.new(#arr.length){LineAnalyzer.new}
#i=0
#analyzer.each do |obj|
obj(#arr[#i],#i)
#i+=1
end
end
def calculate_line_with_highest_frequency()
#highest_count_across_lines = ##higest_wf_count.max
#i=0
##highest_wf_count.each do |count|
#highest_count_words_across_lines.push ##highest_wf_words[#i] if count==#highest_count_across_lines
#i+=1
end
end
The above code is to calculate word frequency in a text file
Whenever I try to run this below command I get the following error int the intialize function in LineAnalyzer class
ruby module2_assignment.rb test.txt
Error : `initialize': wrong number of arguments (given 0, expected 2) (ArgumentError)
Since I am a beginner in Ruby I can't figure out the error.
The issue is in this line
#analyzers=Array.new(#arr.length){LineAnalyzer.new}
LineAnalyzer's constructor requires two parameters, you're passing none
well, the issue of initialize: wrong number of arguments can be resolved in passed arguments into LineAnalyzer.new, but we still have broken script after those changes, so, as I see, this script in [WIP] status, and we need to make some more changes to make it works.
If you can share more details about the goal of analyzing here, it would be nice.
so, go to code, we need to remove call from this line:
calculate_word_frequency(#content,#line_number)
and fix initializer logic here:
def initialize
#analyzers=[]
#highest_count_across_lines=0
#highest_count_words_across_lines=[]
end
def analyze_file()
#arr=IO.readlines(ARGV[0])
#i=0
#arr.each do |line|
#analyzers << LineAnalyzer.new(line,#i)
#i+=1
end
end
btw you have a typo in this line:
#highest_count_across_lines = ##higest_wf_count.max
should be:
#highest_count_across_lines = ##highest_wf_count.max
so, we've resolved issue, but it still not good, coz output is nothing:
ruby module2_assignment.rb test.txt
Test text
Test text
Test text
1
1
1
coz should be something like this:
module2_assignment.rb test.txt
1
2
3
"The following words have the highest word frequency per line: "
"[\"test\", \"text\"] (appears in line 1)"
"[\"test\", \"text\"] (appears in line 2)"
"[\"test\", \"text\"] (appears in line 3)"
So, I think we have 2 options here:
invest some more efforts to make it works
try to find a similar solution
we can use this worked solution of module2_assignment, for example:
https://github.com/zbristor/rubyWordFrequency/blob/2417324381378f6be76485f6271465cd641ec0ff/module2_assignment.rb
I hope it's help
Related
ArgumentError: wrong number of arguments (given 0, expected 1).
The code opens the file and looks at the paragraph and counts, the error
is in the center of the code. An error occurs when a method is called(1).
I can’t understand how to pass the argument methods.
#books = "You can use this knowledge to create small tools that might help."
require "colorize"
class Filecalculation
def select
loop do
puts "# Will we search : calculation_lines paragraph(1)".cyan
print "\n>>>>>> ".yellow
input = gets.chomp
search_method = "calc_#{input}"
if (respond_to?(search_method))
I can’t understand how to pass the argument to this place.
contents = send(search_method, #books)
else
puts "Unknown input: #{input.inspect}, method #{search_method} not defined."
end
end
end
# =================== calc_1 сounting words in Text File
def calc_1 paragraph
word_count = paragraph.split.length
puts "#{word_count} words"
end
end
Filecalculation.new.select
If you call send(search_method) you call a method without arguments. To pass arguments to the method being called, you need to pass them as next send args:
send(search_method, arg1, arg2)
in your case
send(search_method, paragraph)
Docs
How can I find the line of the beginning and end of a Ruby method given a ruby file?
Say for example:
1 class Home
2 def initialize(color)
3 #color = color
4 end
5 end
Given the file home.rb and the method name initialize I would like to receive (2,4) which are the beginning and end lines.
Finding the end is tricky. The best way I can think of is to use the parser gem. Basically you'll parse the Ruby code into an AST, then recursively traverse its nodes until you find a node with type :def whose first child is :initialize:
require "parser/current"
def recursive_find(node, &block)
return node if block.call(node)
return nil unless node.respond_to?(:children) && !node.children.empty?
node.children.each do |child_node|
found = recursive_find(child_node, &block)
return found if found
end
nil
end
src = <<END
class Home
def initialize(color)
#color = color
end
end
END
ast = Parser::CurrentRuby.parse(src)
found = recursive_find(ast) do |node|
node.respond_to?(:type) && node.type == :def && node.children[0] == :initialize
end
puts "Start: #{found.loc.first_line}"
puts "End: #{found.loc.last_line}"
# => Start: 2
# End: 4
P.S. I would have recommended the Ripper module from the standard library, but as far as I can tell there's no way to get the end line out of it.
Ruby has a source_location method which gives you the file and the beginning line:
class Home
def initialize(color)
#color = color
end
end
p Home.new(1).method(:initialize).source_location
# => ["test2.rb", 2]
To find the end, perhaps look for the next def or EOF.
Ruby source is nothing but a text file. You can use linux commands to find the method line number
grep -nrw 'def initialize' home.rb | grep -oE '[0-9]+'
I have assumed that the file contains the definition of at most one initialize method (though generalizing the method to search for others would not be difficult) and that the definition of that method contains no syntax errors. The latter assumption is probably required for any method to extract the correct line range.
The only tricky part is finding the line containing end that is the last line of the definition of the initialize method. I've used Kernel#eval to locate that line. Naturally caution must be exercised whenever that method is to be executed, though here eval is merely attempting to compile (not execute) a method.
Code
def get_start_end_offsets(fname)
start = nil
str = ''
File.foreach(fname).with_index do |line, i|
if start.nil?
next unless line.lstrip.start_with?('def initialize')
start = i
str << line.lstrip.insert(4,'_')
else
str << line
if line.strip == "end"
begin
rv = eval(str)
rescue SyntaxError
nil
end
return [start, i] unless rv.nil?
end
end
end
nil
end
Example
Suppose we are searching a file created as follows1.
str = <<-_
class C
def self.feline
"cat"
end
def initialize(arr)
#row_sums = arr.map do |row|
row.reduce do |t,x|
t+x
end
end
end
def speak(sound)
puts sound
end
end
_
FName = 'temp'
File.write(FName, str)
#=> 203
We first search for the line that begins (after stripping leading spaces) "def initialize". That is the line at index 4. The end that completes the definition of that method is at index 10. We therefore expect the method to return [4, 10].
Let's see if that's what we get.
p get_start_end_offsets(FName)
#=> [4, 10]
Explanation
The variable start equals the index of the line beginning def initialize (after removing leading whitespace). start is initially nil and remains nil until the "def initialize" line is found. start is then set to the index of that line.
We now look for a line line such that line.strip #=> "end". This may or may not be the end that terminates the method. To determine if it is we eval a string that contains all lines from the one that begins def initialize to the line equal to end just found. If eval raises a SyntaxError exception that end does not terminate the method. That exception is rescued and nil is returned. eval will return :_initialize (which is truthy) if that end terminates the method. In that case the method returns [start, i], where i is the index of that line. nil is returned if no initialize method is found in the file.
I've converted "initialize" to "_initialize" to suppress the warning (eval):1: warning: redefining Object#initialize may cause infinite loop)
See both answers to this SO question to understand why SyntaxError is being rescued.
Compare indentation
If it is known that "def initialize..." is always indented the same amount as the line "end" that terminates the method definition (and no other lines "end" between the two are indented the same), we can use that fact to obtain the beginning and ending lines. There are many ways to do that; I will use Ruby's somewhat obscure flip-flop operator. This approach will tolerate syntax errors.
def get_start_end_offsets(fname)
indent = -1
lines = File.foreach(fname).with_index.select do |line, i|
cond1 = line.lstrip.start_with?('def initialize')
indent = line.size - line.lstrip.size if cond1
cond2 = line.strip == "end" && line.size - line.lstrip.size == indent
cond1 .. cond2 ? true : false
end
return nil if lines.nil?
lines.map(&:last).minmax
end
get_start_end_offsets(FName)
#=> [4, 10]
1 The file need not contain only code.
I have this following function but somehow it doesn't get inside the if statement. This is my gist on line 68
I'm trying to evaluate if an object.country name has the same name as "example_of_a_country_name"
def find_population_of_country(liste_pays, country_name)
given_country_population = 0
liste_pays.each do |n|
if (n.country.eql?(country_name.upcase))
given_country_population = n.population
#I'm trying to see if it's output something here
puts country_name.upcase
end
return given_country_population
end
end
can you type this within your function and tell me what you get?:
def find_population_of_country(liste_pays, country_name)
liste_pays.select {|n| n.country.eql?(country_name.upcase) }
end
end
The problem is your line:
return given_country_population
This should be moved one line up, inside the if ... end block for the name comparison, otherwise, it's returning even for non-matches.
I was working through the about_sandwich_code example in the Ruby Koans example, completed code link here about_sandwich_code.rb for reference. The following is the relevant reference code for easy reference.
def count_lines(file_name)
file = open(file_name)
count = 0
while file.gets
count += 1
end
count
ensure
file.close if file
end
def test_counting_lines
assert_equal 4, count_lines("example_file.txt")
end
# ------------------------------------------------------------------
def find_line(file_name)
file = open(file_name)
while line = file.gets
return line if line.match(/e/)
end
ensure
file.close if file
end
def test_finding_lines
assert_equal "test\n", find_line("example_file.txt")
end
def file_sandwich(file_name)
file = open(file_name)
yield(file)
ensure
file.close if file
end
In my attempt at writing find_line2 method I tried the following code which compiled.
def find_line2(file_name)
file_sandwich(file_name) do |file|
while file.gets
return file.gets if file.gets.match(/e/)
end
end
end
def test_finding_lines2
assert_equal "test\n", find_line2("example_file.txt")
end
For reference, example_file.txt.
However, the koans returned the following in the terminal window: Expected "test\n" to equal nil
This raised my awareness as the penultimate koan code/test for the analogous finding lines function pre-sandwich code solved that koan.
def test_finding_lines
assert_equal "test\n", find_line("example_file.txt")
end
As I tried different options, I realized that the following find_line2 implementation
def find_line2(file_name)
file_sandwich(file_name) do |file|
while line = file.gets
return line if line.match(/e/)
end
end
When run with
def test_finding_lines2
assert_equal "test\n", find_line2("example_file.txt")
end
resolves the koan rather than tell me that the test should equal nil as the prior screenshot shows. So what this amounts to, as I understand in this moment is that my first implementation somehow changes what the koan program expects as the check, which sort of baffles me. I think it means my attempt somehow broke the koan, but I'm not sure why. Actually, after running file_sandwich and my first implementation of find_line2 I see the call find_line2("example_file.txt") to return nil, so for some reason file.gets acts differently than using line after the line = file.gets in the while statement.
Can someone explain why my first implementation and the answer don't equal? I believe that the answer lies in a more clear understanding of blocks?
def find_line2(file_name)
file_sandwich(file_name) do |file|
while file.gets #gets the next line in the file
if file.gets.match(/e/) #gets the next line and checks for a match
return file.gets #gets the next line and returns it.
end #restructured for clarity
end
end
end
So with the example file: This\nis\na\ntest you code gets This\n, gets is\n and checks it (fail). On the next iteration, your code gets a\n, gets test\n and checks it (true), then gets the next line (nil) and returns it.
I'm almost a Ruby-nOOb (have just the knowledge of Ruby to write some basic .erb template or Puppet custom-facts). Looks like my requirements fairly simple but can't get my head around it.
Trying to write a .erb template, where it reads a file (with space delimited lines) to an array and then handle each array element according to the requirements. This is what I got so far:
fname = "webURI.txt"
def myArray()
#if defined? $fname
if File.exist?($fname) and File.file?($fname)
IO.readlines($fname)
end
end
myArray.each_index do |i|
myLine = myArray[i].split(' ')
puts myLine[0] +"\t=> "+ myLine.last
end
Which works just fine, except (for obvious reason) for the line that is commented out or blank lines. I also want to make sure that when spitted (by space) up, the line shouldn't have more than two fields in it; a file like this:
# This is a COMMENT
#
# Puppet dashboard
puppet controller-all-local.example.co.uk:80
# Nagios monitoring
nagios controller-all-local.example.co.uk::80/nagios
tac talend-tac-local.example.co.uk:8080/org.talend.admin
mng console talend-mca-local.example.co.uk:8080/amc # Line with three fields
So, basically these two things I'd like to achieve:
Read the lines into array, stripping off everything after the first #
Split each element and print a message if the number id more than two
Any help would be greatly appreciated. Cheers!!
Update 25/02
Thanks guy for your help!!
The blankthing doesn't work for at all; throwing in this error; but I kinda failed to understand why:
undefined method `blank?' for "\n":String (NoMethodError)
The array: myArray, which I get is actually something like this (using p instead of puts:
["\n", "puppet controller-all-local.example.co.uk:80\n", "\n", "\n", "nagios controller-all-local.example.co.uk::80/nagios\n", ..... \n"]
Hence, I had to do this to get around this prob:
$fname = "webURI.txt"
def myArray()
if File.exist?($fname) and File.file?($fname)
IO.readlines($fname).map { |arr| arr.gsub(/#.*/,'') }
end
end
# remove blank lines
SSS = myArray.reject { |ln| ln.start_with?("\n") }
SSS.each_index do |i|
myLine = SSS[i].split(' ')
if myLine.length > 2
puts "Too many arguments!!!"
elsif myLine.length == 1
puts "page"+ i.to_s + "\t=> " + myLine[0]
else
puts myLine[0] +"\t=> "+ myLine.last
end
end
You are most welcome to improve the code. cheers!!
goodArray = myArray.reject do |line|
line.start_with?('#') || line.split(' ').length > 2
end
This would reject whatever that either starts with # or the split returns an array of more than two elements returning you an array of only good items.
Edit:
For your inline commenting you can then do
goodArray.map do |line|
line.gsub(/#.*/, '')
end