I would like to create an array in Ruby rake called ARRAY where each line of an infile ("infile.txt") is an element of the array.
This is how I have tried it so far:
desc "Create new array"
task :new_array do
ARRAY=Array.new
end
desc "Add elements to array"
task :add_elements => [:new_array] do
File.open("infile.txt").each do |line|
ARRAY.push(#{line})
end
end
However, I get the following error:
syntax error, unexpected keyword_end, expecting ')'
for the end after "ARRAY.push(#{line})"
Can someone explain to me what the problem is or let me know of another way to do this?
Many thanks!
Your problem is that you're trying to use string interpolation (#{...}) outside a string:
ARRAY.push(#{line})
# ---------^^^^^^^
You could use string interpolation by throwing in some double quotes:
ARRAY.push("#{line}")
but there's no need to convert a string (line) to an identical string ("#{line}") so you could just push straight onto the array:
ARRAY.push(line)
Or you could just skip all that explicit iteration and use #to_a:
array = File.open("infile.txt").to_a
And if you wanted to strip off the newlines:
array = File.open('infile.txt').map(&:chomp)
As engineersmnky points out in the comments, using File.readlines would be a better approach:
array = File.readlines('infile.txt')
array = File.readlines('infile.txt').map(&:chomp)
#...
And don't forget to check IO as well as File for methods when working with files.
You can also do this:
array = []
IO.foreach("path/to/file.txt") { |line|
array.push(line.chomp)
}
Then if you want to clear the array from empty lines just use delete:
array.delete("")
Related
Problem
I am building a script that takes in a column from a CSV that can contain 0 or more ID numbers.
I have created an array of the column, however, since some cells have no ID number and some have multiple,I have an array of arrays.
I want to create an array where each element is a single ID (i.e split the IDs from each element in the array to a single element).
Here is my code so far:
require 'csv'
class MetadataTherapyParser
def initialize (csv)
#csv = csv
end
def parse_csv
therapy_array = []
CSV.foreach(#csv) do |csv_row|
therapy_array << csv_row[0]
end
end
def parse_therapies(therapy_array)
parsed_therapy_array = therapy_array.flatten!
puts parsed_therapy_array
end
end
metadata_parse = MetadataTherapyParser.new ("my_csv_path")
metadata_parse.parse_csv
metadata_parse.parse_therapies(metadata_parse)
Actual Results
I am getting the following error:
in `parse_therapies': undefined method `flatten' for #<MetadataTherapyParser:0x00007fd31a0b75a8> (NoMethodError)
From what I can find online, flatten is the method to use. However I can't seem to figure out why I am getting an undefined method error. I have checked to ensure that therapy_array is indeed an array.
If anyone has encountered this issue before and could offer some advice, it would be greatly appreciated!
Thank you in advance.
While calling the method parse_therapies instead of passing an array you are passing the metedata_parse, which is an object of MetadataTherapyParser
Try this:
def parse_csv
therapy_array = []
CSV.foreach(#csv) do |csv_row|
therapy_array << csv_row[0]
end
therapy_array
end
Then while calling the methods:
metadata_parse = MetadataTherapyParser.new ("my_csv_path")
therapy_array = metadata_parse.parse_csv
metadata_parse.parse_therapies(therapy_array)
This should pass an Array instead of MetadataTherapyParser object to your parse method.
This is my code -
Here I'm trying to get all the constants which has feature_toggle string attached to it, by searching through all the files using a regex, which has been cloned from the git and stored locally, for example,
feature_enabled?(TEST_ONE)
feature_enabled?(TEST_TWO)
feature_enabled?(TEST_THREE)
feature_enabled?(TEST_FOUR)
feature_enabled?(KEY_AS_PRIMARY)
From this I'll be getting following values in matches_found
["TEST_ONE", "TEST_TWO", "TEST_THREE","TEST_FOUR","KEY_AS_PRIMARY"]
This is the method where I'm trying to achieve that.
# public: retrieve the constant feature names based on the asset passed
#
# filename - path of each file under a repository for running the scan for example - /Users/sagarPC/Desktop/project/tmp/icdev/somefolder/app/models/project_one/orion/add_me_task.rb
# pattern - regex pattern which search for the names.Ex- /(?:\.|!)?feature_enabled\?\((.*?)\)/m
#
# Ex - feature_enabled?(TEST_ONE)
#
# returns each constant's value in an array
# Ex - [testone,testtwo,testthree,testfour]
def self.constant_discovery(file_name, pattern)
matches = File.open(file_name).read.scan(pattern).uniq.flatten.compact
matches_found = matches.map {|key| key.split(',')[0].scan(/^[A-Z]+(?:_[A-Z]+)*$/)}.flatten
search_pattern = /([A-Z]+_)*[A-Z]+ = '.+'/
File.open(file_name) do |f|
lines = f.find_all {|line| line =~ search_pattern }
lines.each do |line|
if line.include?('=')
print line unless line.empty?
required_output = matches_found & line
end
line
end
end
matches
end
By the above code I'm getting matches_found values like below,
["TEST_ONE", "TEST_TWO", "TEST_THREE","TEST_FOUR","KEY_AS_PRIMARY"]
Where as, line is producing output like this,
TEST_ONE = 'testone'
TEST_TWO = 'testtwo'
TEST_THREE = 'testthree'
TEST_FOUR = 'testfour'
These constants can be declared somewhere in the cloned repository and can be used used somewhere else.
In the require_output I need to get the common constants values between matches_found and line, from those common constants return only those which are declared somewhere and has values assigned to it. The value of the constant can be declared anywhere in the cloned repo.
When I tried to do this I'm facing issue while comparing matches_found and line with error message saying "failed with error no implicit conversion of String into Array "
By this I understood that I have to convert values of line to an array. And then should compare it with matches_found, after this I'll be getting common constant from both the arrays in required_output. And later I can get those values which has been assigned to those common constants.
In the end, the method should produce following return values,
[testone,testtwo,testthree,testfour]
As I'm very new to ruby can someone please help me with it?
Sorry for pasting my whole method. Please help me to resolve this.
I'm just getting started in ruby and I have some trouble understanding the scan method:
my_string = "0000000001000100"
string_group = my_string.scan('/...../')
puts string_group
puts string_group.class
It displays that I've got an array but the array is empty. It can't come from my regex because I tested it and tried with another one:
'/[01]{5}/'
Why do I get an empty array?
Because regexes in Ruby are literal, not strings -- you have single quotes around your regex, so scan is searching for the literal string /...../ rather than matches to the regex /...../. Try this instead:
my_string = "0000000001000100"
string_group = my_string.scan(/...../)
Which gives this:
["00000", "00001", "00010"]
For example, I have a string A-456-BC-123;DEF-456;GHI-789. And I need to search for second part:DEF-456 with keyword 456. The potential problem here is that the first part A-456-BC-123 also has the keyword 456. Currently my logic is that, split the string first using ;, split each of it again using -, get the last item of this Array, search keyword 456. Another thing is that I don't want to do a full keyword match like DEF-456, I only want to use 456 as keyword to locate DEF-456, in other words, 456 should be the last segment of the string I want.
Here are my codes:
FirstSplit= split("A-456-BC-123;DEF-456;GHI-789",";")
For each code in FirstSplit
SecondSplit = split(FirstSplit,"-")
'get Array Count
Count = Ubound(SecondSplit)
'get the last item in Array
If SecondSplit(Count-1) = "456" Then
'doing something
End if
Next
Currently, an error will generate at SecondSplit(Count-1), saying that "Subscript out of range: '[number: -1]'"
Could someone tell me how to fix it?
The real problem is here:
SecondSplit = Split(FirstSplit, "-")
You should be splitting your element which you've stored in variable code from your For Each loop. By trying to split an array you should be getting a Type Mismatch error, but perhaps vbscript is forgiving enough to attempt and return a 0 element array back or something. Anyway:
SecondSplit = Split(Code, "-")
Also, to look at the last element just use:
If secondSplit(Ubound(SecondSplit)) = "456" Then
Subtracting 1 from the ubound would get you the second to last element.
You don't need to split it twice - what you're looking for is Right():
FirstSplit = split("A-456-BC-123;DEF-456;GHI-789",";")
For each code in FirstSplit
If Right(code, 3) = "456" Then
' do something
End If
Next
Though this would also match an entry like ABC-1456. If the - symbol is a required delimiter, you'd have to say If Right(code, 4) = "-456".
I wrote a code in which i would like to split a number of rows along each column that it is represented in based on a delimiter. I wrote a for loop in which it does it for me.
Pdbindex is a cell array, where my values are stored that i am trying to split with a delimiter, a colon (:).
for i = pdbindex(:,1)
clean2_pdb = split(':', pdbindex);
end
However, it threw me an error stating, Undefined function or method 'split' for input arguments of type 'cell'..
I don't know to solve this.
Please advise.
Update:
I have also posted another question of using strsplit function. A different problem pops up.
Link : Strsplit function
There's no such function called split. What you want is:
for i = 1:size(pdbIndex, 1)
clean2_pdb = regexp(pdbIndex{i,1}, ':', 'split');
end
Another way can be accessing the cell data as a string and then using strsplit func on the cell contents.
for i = 1:size(pdbIndex, 1)
clean2_pdb = strsplit(pdbIndex{i},':')
end