def file_to_array(filename)
my_text = []
File.open(filename, "r").each do |line|
my_text << line
end
my_text
end
Hello! My method is supposed to receive a filename when called, open the file and move each line to an array. However, it raises undefined local variable when called and I'm assuming it has something to do with the filename[DOT]ext ?!
My call happens in a method below
def clean_array
cleaned = file_to_array(text.txt).map do |element|
element.gsub(/\b['s\!\.\\n]*/m, "")
end
cleaned.map! do |el|
el.split(" ")
end
return cleaned.flatten!
#p cleaned
end
The file name should be a string, and as such, passed in quotes:
file_to_array("text.txt")
# OR
file_to_array('text.txt')
Related
I am learning ruby and getting this error
My code:
class New_class
hash{}
File.readlines('file.txt').each do |line|
if (line =~ /^(\w+)=>(.*)/)
hash[$1] =$2
end
end
def check
a='2345'
value = hash.fetch{a,''}
if (value == '')
puts 'Error no value found'
else
puts value
end
end
end
var=New_class.new
var.check
Error :undefined method 'fetch'
Here I want hash to run one time and store all the key/value so that I can use the hash in multiple methods and check for values. Anyone know how to fix this error or any better way to do?
The hash variable is out of scope. You can make it global by changing it to $hash.
Also fetch uses round brackets not curly brackets.
class New_class
$hash = {}
File.readlines('file.txt').each do |line|
if (line =~ /^(\w+)=>(.*)/)
$hash[$1] =$2
end
end
def check
a='2345'
value = $hash.fetch(a,'')
if (value == '')
puts 'Error no value found'
else
puts value
end
end
end
Undefined method for nil:Nilclass
In a class, a method counts the number of words in a paragraph.An error occurs when a method is called(1). I can’t understand how to pass the argument methods using send.
If I remove the class and put the def calc_1(paragraph) method into the loop, then everything works, I start calling the select method. It turns out he does not see my books variable with text, when there is a class.
#books = "You can use this knowledge to create small tools that might help."
class Filecalculation
def select
loop do
puts "# Will we search : сounting words in text File(1)".cyan
print "\n>>>>>> "
input = gets.chomp
search_method = "calc_#{input}".to_sym
if (respond_to?(search_method))
contents = send(search_method, #books)
end
end
end
def calc_1 paragraph
word_count = paragraph.split.length
puts "#{word_count} words"
end
end
Filecalculation.new.select
If replaced by search_method = "calc_#{input}".to_sym also works.
Helped add def initialize #books end.
Instead of contents = send (search_method, #books) you can use send (search_method, #books).
require "colorize"
class Filecalculation
def initialize
#books = "You can use this knowledge to create small tools that might help you."
end
def calc_1 paragraph
word_count = paragraph.strip.squeeze(' ').count(' ') + 1
puts "#{word_count} words"
end
def select
loop do
puts "# Will we search : Calculation_lines paragraph(1)".cyan
print "\n>>>>>> ".yellow
input = gets.chomp
search_method = "calc_#{input}" #.to_sym
if (respond_to?(search_method))
contents = send(search_method, #books)
else
puts "exit "
exit
end
end
end
end
Filecalculation.new.select
I'm creating a program to create folder structure from the text file.
In that I need to get the spaces that comes before any word in the given line.
How can I implement this functionality in ruby without opening String class?
I come from C# and it's very easy to extract methods in it. But I don't know how rubyists approach the same problem!
Here is the half of the program that I have written.
require "FileUtils"
#lines_array = []
def file_to_array
file = File.open("fs.txt", "r") do |file|
file.each_line do |line|
#lines_array << line.rstrip
#lines_array.reject! {|l| l.empty?}
end
end
end
def creation
#lines_array.each do |i|
if ( /(.+)\.(\w+)/ =~ i )
FileUtils.touch i
else
FileUtils.mkdir_p i
end
end
end
def count_space
beginning = s.length - s.lstrip.length
beginning
end
How can I extract logic from file_to_array method? And how can I implement and use count_space on elements of #lines_array?
here is the solution:
s = ' aaa ' #3 spaces in start and after `aa` there are two spaces
s[/\A */].size # for blank spaces in start of string
=> 3
s[/ *\z/].size # for blank spaces a the end of string
=> 2
So if I understand you correctly, you want to be able to call the #count_spaces method on your lines. Well there are three ways to approach this.
Open up the String class (what you don't want to do)
Create a class that inherits from Sting
Create a class that contains the string as an instance variable (this is probably your prefered method)
Open the class
class String
def count_spaces
#code here
end
end
Inherited class
class FileSystemLine < String
def count_spaces
#code here
end
end
Class with data in instance variable
class FileSystemLine
def initialize(line)
#line = line
end
def count_spaces
#code here
# make sure that code acts on #line
# like #line.length - #line.strip.length
end
# If you want to keep string functionalities, you could look up ruby delegation or use this simple method_missing method
def method_missing(method, *args, &block)
if #line.respond_to?(method)
#line.__send__(method, *args, &block)
else
super
end
end
end
Just remember to initialize the class.
Option 1. remains the same, option 2. and option 3. both look like this: line = FilSystemLine.new(line)
So your code would look like:
#lines_array = []
def file_to_array
file = File.open("fs.txt", "r") do |file|
file.each_line do |line|
#lines_array << FileSystemLine.new(line.rstrip)
#lines_array.reject! {|l| l.empty?}
end
end
end
This is a class method. So far this is what I have:
def self.save(array, my_file)
File.open(my_file) do |f|
f.lines.each do |line|
text_line = line
text_line.write
end
end
end
I'd do as below:
def self.save(array, my_file)
File.open(my_file,'w') do |f|
f.puts array
end
end
IO::puts, if called with an array argument, writes each element on a new line. You don't need to close the file manually, as you called IO::open. As per the doc of IO::open, if the optional code block is given, it will be passed io as an argument, and the IO object will automatically be closed when the block terminates.
Use File#puts which is inherited from IO#puts
def self.save(array, my_file)
File.open(my_file, 'w+') do |f|
array.each do |line|
f.puts line
end
end
end
class DobbsyKretts
def initialize
#Receive idea
puts "Enter an idea, a secret or anything else you want to secretize; hit enter to stop typing and save the file"
(#idea = gets).reverse.upcase
#Filename and saving - to encrypt the file
puts "Enter the file name you'd like to have this saved as; Type PLAN at the beginning for plans and REM for reminders"
(#file_name = gets.chomp.upcase)
File::open("DobbsyKrett-"+ #file_name + ".txt", "w") do |f|
f << #idea
end
end
def unzip
puts "Do you want to withdraw PLAN or REM"
response = gets.chomp.upcase!
puts "Invalid" if !["PLAN","REM"].include?(response)
file_contents = nil
Dir['DobbsyKrett-'+response+"*.txt"].each do |file_nom|
file_contents = File.read(file_nom)
end
puts file_contents
end
end
somethingsomething1 = DobbsyKretts.new
somethingsomething1.unzip
def unzip
puts "Do you want to withdraw PLAN or REM"
#response = gets.strip
if #response.downcase != "plan" and #response.downcase != "rem"
puts "Invalid" end
Dir["DobbsyKrett-"+#response+".txt"].each do |file_nom|
#value = file.read(file_nom)
end
puts #value
end
end
The function gets will return a string with the line-ending character at the end which is not what you expected. To remove it, use the chomp function:
#response = gets.chomp
It is okay for a method (e.g. unzip) to create new instance variables (e.g. #valueholder). In general it's always better for your variables to have the smallest possible scope, so unless you need to read valueholder later, you should just use a local variable (remove the # from the name):
Dir["DobbsyKrett-"+#response+".txt"].each do |file_nom|
valueholder = File.read(file_nom)
end
puts valueholder
Also, valueholder is a terrible name for a variable but if you made it a local variable that could be excused.
Also, your block startings/endings are mismatched. Here's a fixed version of your function that shouldn't result in syntax errors:
def unzip
puts "Do you want to withdraw PLAN or REM"
response = gets.chomp.downcase
if !["plan","rem"].include? response
puts "Invalid"
else
Dir["DobbsyKrett-#{response}.txt"].each do |file_nom|
valueholder = file.read(file_nom)
end
puts valueholder
end
end
Edit: You should capitalize File to correctly call File.read.