I'm writing a little system that parses lines of data in a txt separated by commas,
so to be basic about it I read the file lines into an array, then use .each on the array and split everything by "'" then push it into the holding array which is returned as the database made from the file, I have made two, the first works fine but its data is stored line by line with a keyword, this one works fine, access and return all good.
I'm using a file containing text data like this
476,TACKLE,40,25,30,0,0,1,A3F,move description string with, punctuation and t's
477,ANOTHERATTACK,BLAHBLAHBLAH,1,2,3,4
This would be data parsing kind of right, well
so I go:
$fs = File_SYstem.new
#path = Dir.getwd.to_S + "/desktop/file.txt"
#data_lines = $fs.file_read_lines(#path)
#data = []
#data_lines.each do |line|
#data >> line.split(',')
end
return #data
#this would make an array of the lines, each line being an array of its elements, right?
#data = The_Code_Above_In_A_Class.new(#path)
=>#data
#data[0]
=>"354,FISSURE,10,40,50,blah blah blah, the second half of the text."
#hmmmm
#data[0][0]
=>"354"
So it seems to work fine, but some times, the numbers at the beginning come back as bytes :O
And for example:
#data.each do |line|
puts line[1].to_S #return second element which is name of move
end
This would print a list of the expected names, fine and dandy, but then I get the remaining data I didn't ask for returned below it in an unrecognizable pattern.
Maybe I can do this?
array = [1,2,3]
array = [array,array,array]
array[2][0] = "Hello!"
array.each do |item|
puts item[2]
end
=>"3"
"3"
"Hello!"
=>:
Seems to me this should work since I'm already using close variations of this style somewhere else with success.
Now this is a sample of the real 580 line file:
1,MEGAHORN,Megahorn,000,120,BUG,Physical,85,10,0,00,0,abef,Cool,"Using its tough and impressive horn, the user rams into the target with no letup."
2,ATTACKORDER,Attack Order,000,90,BUG,Physical,100,15,0,00,0,befh,Smart,The user calls out its underlings to pummel the target. Critical hits land more easily.
3,BUGBUZZ,Bug Buzz,046,90,BUG,Special,100,10,10,00,0,bek,Cute,The user vibrates its wings to generate a damaging sound wave. It may also lower the target's Sp. Def stat.
Now this is the class I use to load it up:
class Move_Data_Extracter
def initialize(path)
load $path.to_s + "/source/string_helper.rb"
#load "/mnt/sdcard/pokemon/system/source/string_helper.rb"
#path = path.to_s
#file_lines = $file_system.file_read_lines(#path.to_s)
$movedata = []
#file_lines.each do |line|
$movedata << line.split(",")
end
end
def get_move_id(move_name)
$movedata.each do |move|
if move[1].upcase.to_s == move_name.upcase.to_s
return move[0].to_i
else
return "Move Doesnt Exist In The System!"
end
end
end
end
This is the feedback I got when I accessing the first item in the returned array(s?):
irb(main):002:0> $movedata[0]
=> ["\xEF\xBB\xBF1", "MEGAHORN", "Megahorn", "000", "120", "BUG", "Physical", "8
5", "10", "0", "00", "0", "abef", "Cool", "\"Using its tough and impressive horn
", " the user rams into the target with no letup.\"\n"]
irb(main):003:0> $movedata[0][0]
=> "\xEF\xBB\xBF1"
irb(main):004:0>
Access worked ok this time but the first element is bytes and that each method I'm trying is going so wrong.
Can anyone figure out whats wrong here?
First thing, that's obviously not the code you're using as things like to_S aren't part of ruby and would instantly fail anyway.
Let's clean up the code a bit:
# $fs = File_SYstem.new # this is just not needed
path = File.expand_path "/desktop/file.txt" # instance variables *only* within explicit objects
data_lines = File.read( path ).split ","
I've no idea what the rest of what you've written really means.
This outputs:
# => ["476", "TACKLE", "40", "25", "30", "0", "0", "1", "A3F", "move description string with", " punctuation and t's\n477", "ANOTHERATTACK", "BLAHBLAHBLAH", "1", "2", "3", "4"]
This bit of code - what is it?
array = [1,2,3]
array = [array,array,array] # pure craziness!
array[2][0] = "Hello!"
array.each do |item|
puts item[2]
end
=>"3"
"3"
"Hello!"
=>:
As to why you're getting back bytes, it's because the file is (likely) encoded as UTF-8. Try File.read( path, "r:UTF-8") to get Ruby to use the correct encoding.
Related
I have a single string, achieved using backticks of the following form:
output = `git log`
then, I have splitted the result where there are "\n" and the result went into an array of the form:
array = output.split("\n")
then, I am just trying to output the result in the screen, however, when I am using
array.each do |a|
puts a
end
I am getting as a result a double line of the form:
result after puts
(empty line)
result after puts etc
when my preferred result is a single line of the form:
result after puts
result afters puts etc
I tried to perform this with print, but I am getting:
result after puts result after puts etc
in a single line.
Can you please help me?
The issue is when you split using \n, if there are two \n characters then an empty "" gets added to the array.
eg: test = ["this","","is","test"]
Now if you do,
test.each do |a|
puts a
end
The o/p will be,
this
// a new line will come here.
is
test
so you should reject the empty values,
test2 = test.reject{ |value| value == ""}
test2.each do |a|
puts a
end
Result is,
this
is
test
In same way,
output = `git log`
array = output.split("\n")
array2 = array.reject{ |value| value == ""}
array2.each do |a|
puts a
end
This will give you the correct result.
Thanks to #AndreyDeineko, we have that:
"The issue is when you split using \n if there are two \n characters then an empty "" gets added to the array. Howcome? a = "1\n2\n3\n4\n"; a.split("\n") #=> ["1", "2", "3", "4"].
Therefore, array.each { |a| a } will work for you"
It did not work 100% for me, but using his answer, I manage to achieve the required result which is:
array.each { |a| a }
puts array
sorry if this is a simple solution, but I'm trying to grab all the numbers from a file into an array. The file I'm importing reads
3 5 10
2 7 15
This is my code
grab = Array.new
IO.foreach("test.txt") do |line|
grab = line.chomp(" " + "/n").split
end
p grab
When I do this, it prints the last line of numbers, yet when I print it from the IO block, it prints 2 arrays. First and second line.
If you want to consolidate this into a singular array:
grab = [ ]
IO.foreach("test.txt") do |line|
grab.concat(line.chomp.split)
end
Another way:
grab = IO.readlines("test.txt").flat_map do |line|
line.chomp.split
end
You should do something like
grab << line.chomp(" " + "/n").split
This gives you what you're looking for:
grab = IO.foreach("test2.txt").map {|line| line.split(/\D/) }.flatten
puts "#{grab}"
This produces the single array output:
["3", "5", "10", "2", "7", "15"]
It can all be wrapped up into a nice, tidy one-liner if you prefer it that way:
grab = IO.foreach("test2.txt").map {|line| line.split(/\D/) }.flatten
puts "#{grab}"
If you want to do an integer conversion in the process, you can modify the line.split to this:
grab = line.split(/\D/).map(&:to_i)
That change will produce this output:
[3, 5, 10, 2, 7, 15]
An instance variable in my code keeps on having its value reassigned despite no commands for it to do so. Essentially, the variable is only called in twice: once, to assign its value at startup and then to copy its value to another variable. The code I am working on is a bit complex for me to post it here completely, but this is a basic rundown of it:
class Test
def self.initialize
#problem_var = [ ["1 2 3", "4 5 6"], ["a b c", "d e f"], ["bar", "foo"] ]
end
def self.main_method(parVar)
data = #problem_var
result = "Lorem"
#Iterate through subarrays
data.each do |dataBlock|
#Some code here
if condition then
#The first subarray meets the condition
char = dataBlock[1]
#At this point char is equal to "4 5 6"
##problem_var still holds its original value of:
# [ ["1 2 3", "4 5 6"], ["a b c", "d e f"], ["bar", "foo"] ]
result = OtherModule.replace_six(char)
#By this point, char is now equal to "4 5 7"
#Curiously #problem_var is now equal to:
# [ ["1 2 3, "4 5 7"], ["a b c", "d e f"], ["bar", "foo"] ]
end
end
#More code here
return result
end
end
Something weird happens to the variable right after result has a value assigned to it. Furthermore, this only seems to happen once so that if the code were to run again and alter that 7 to say... an 8, #problem_var would not be updated. Changing #problem_var to a constant has not been able to prevent it from being altered. I have mulled over this for the past two weeks and haven't been able to figure it out. Anyone know what could be happening?
Edit:
You guys were right! The issue was in OtherModule. I was using gsub! on the parameter variable that received char. Here's the simplified OtherModule code for future reference:
module OtherModule
def replace_six(input)
modified_string = ""
if condition(input) then
#Input meets condition
first_string = replace_numbers(input)
#The following method doesn't really apply here
second_string = replace_letters(first_string)
modified_string = second_string
end
return modified_string
end
def replace_numbers(text)
#Some code here
#The following condition for numbers in `text`
if condition(text) then
text.gsub!("6", numberFunction)
#numberFunction returns a string
end
return text
end
end
Problem is most likely in OtherModule.replace_six.
If it uses String#replace method, then, String is mutated and its effect will be visible everywhere a reference to its has been kept.
If you do not have access to code of OtherModule, then, do this:
result = OtherModule.replace_six(char.dup)
If you have access to code of OtherModule, then, change the implementation of replace_six such that it uses either String#sub or String#gsub, as they return a copy of modified string instead of mutating the original string.
I am new to ruby and was trying out with arrays.i want to print the array in single line.
this is the block of code(please ignore any errors)
array=[]
puts "Choose an option: ","1.Push, 2.Pop, 3.Display Length"
choice=gets.to_i
while choice!=4
if choice==1
puts "enter Number of elements to be pushed"
n=gets.to_i
n.times do
puts "Enter element"
el=gets.to_s
array.push el
end
puts array
elsif choice==2
puts array.pop
elsif choice==3
puts array.length
else
puts "invalid"
end
end
when I print my array in if choice==1i get all the outputs on different lines,
example
hello
i
am
beginner
to
ruby
is there anyway to put the output in single line?
i.e hello i am beginner to ruby
EDIT: I have even tried using puts array.join(' '), but that too doesnt work.
First of all,
puts array
should be
puts array.join(' ')
By default, puts outputs each element on its own line.
Secondly,
el=gets.to_s
should be
el = gets.chomp
gets returns a string, so there's not much point in converting a string to a string. But the string returned by gets will also end with a newline, so you need to chomp that newline off.
Instead of puts array try p array if you want the whole array printed to screen.
New to Ruby as well! I just tried:
puts "#{array.inspect}"
where array = [2 3 4 5 6 77 88]. It resulted in:
["2", "3", "4", "5", "6", "77", "88"]
which is a single line printout, if a quick fix is needed. But array.join(' ') is much better.
Trying to make a method skip_animals that takes an animals array and a skip integer and returns an array of all elements except first skip number of items.
input: skip_animals(['leopard', 'bear', 'fox', 'wolf'], 2)
expected output: ["2:fox", "3:wolf"]
def skip_animals(animals, skip)
arr = Array.new
animals.each_with_index{|animal, index| arr.push("#{animal}:#{index}") }
puts arr.drop(skip)
end
This instead puts each output on a separate line and doesn't add them to the array arr. I thought the arr.push would add them correctly. What do I have to do to get the elements added to the array?
I want to use these methods, not map or something more advanced. I need to tinker with this each_with_index line, not overhaul it.
(This is a challenge on Hackerrank, so it uses STDIN and STDOUT)
EDIT
Here is my updated code with p instead of puts. It's giving me a weird output of two different arrays, not sure why.
def skip_animals(animals, skip)
arr = Array.new
animals.each_with_index{|animal, index| arr.push("#{index}:#{animal}") }
p arr.drop(skip)
end
This gives me two lines of output:
["3:panda", "4:tiger", "5:deer"]
["0:leopard", "1:bear", "2:fox", "3:wolf", "4:dog", "5:cat"]
I'm assuming the top is the correct array, but I don't get why the second is printing also, or why it has a different set of animals.
Use p instead of puts.
irb(main):001:0> puts ['1', '2']
1
2
=> nil
irb(main):002:0> p ['1', '2']
["1", "2"]
According to the documentation, puts:
Writes the given objects to ios as with IO#print. Writes a record
separator (typically a newline) after any that do not already end with
a newline sequence. If called with an array argument, writes each
element on a new line. If called without arguments, outputs a single
record separator.
BTW, I would code like this (using Enumerable#map + returning result instead of printing inside the function):
def skip_animals(animals, skip)
animals.drop(skip).each_with_index.map { |animal, index|
("#{index + skip}:#{animal}")
}
end
p skip_animals(['leopard', 'bear', 'fox', 'wolf'], 2)
just remove puts remove form this line puts arr.drop(skip)
def skip_animals(animals, skip)
arr = Array.new
animals.each_with_index{|animal, index| arr.push("#{animal}:#{index}") }
arr.drop(skip)
end