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.
Related
My task:
Create 2 class objects. Delete all elements in the first object that are contained in the second.
My implementation:
class Vector
def initialize
#vector = Array.new
end
end
vector1 = Vector.new(1,2,3,4,5,6,7)
vector2 = Vector.new(3,6,7)
But this does not work as needed. What should I fix?
I think it is some sort of question from institute, and requirements are different than what you coded, I am just trying to correct your coding and rectify so you get some result, than you can further proceed to full-fill your requirements.
Your first mistake is you are asking for one parameter but providing
commas is giving multiple parameters, so I have changed it to get
array.
As changed array so now you can't add another array in first, as it
is just one array so I am removing << and adding = in initialize
method
Your initialize method is not taking any parameter, but you are
providing, but you have to define a method set_vector so you have
to use that method instead of class, as per your requirement that is
what you want.
You should define - method but than you have to play with class
variables too, as you are playing with two object and with in your
class you have to define - function, but I am here just using your
get_vector method to compare arrays and return your response.
changing put to print so you can have variables instead of all items.
Hope this will give you some helpful insight to coding.
class Vector
def initialize
#vector = Array.new
end
def set_vector=(vector)
#vector = vector
end
def get_vector
#vector
end
end
def confront(first_vector, second_vector)
first_vector.get_vector - second_vector.get_vector
end
first_vector = Vector.new
first_vector.set_vector=[1,2,3,4,5,6,7]
second_vector = Vector.new
second_vector.set_vector=[3,6,7]
final_vector = confront(first_vector, second_vector)
begin
puts "First:"
print first_vector.get_vector
puts "\nSecond:"
print second_vector.get_vector
puts "\nFinal Vector:"
print final_vector
end
this is my first question so i hope I am doiung the tagging and so on right.
I have an array of objects of the same class. When I want to access a property of the objects I can use:
Data = [ObjectArray.property];
Now I want to call a mehtod of the class for each object and get back the result as Vektor/ matrice:
result = [ObjectArray.myfun(X)]
here I get an error saying:
Expected one output from curly brace or dot indexing expression
I tried brute force several different annotation but nothing works and i can't find a solution online.
Anybody knows how to make this work?
Thanks and Cheers!
It's slightly unclear what the structure of your array is, but you should be able to use arrayfun.
result = arrayfun( #(obj) obj.myfun(x), ObjectArray );
If you function myfun returns anything other than a scalar, you will need to set the UniformOutput flag to be false. This will make the result a cell array, with one cell per result.
result = arrayfun( #(obj) obj.myfun(x), ObjectArray, 'uni', false );
% If you want to concatenate results, could use something like
% result = [result{:}];
Note that this is basically shorthand for a loop, but it saves you pre-allocating an output and writing the loop.
You can also do this directly inside of your myfun:
If the item you operate your method on is an array, the first parameter of your myfun method will be an array. This can be used, and call itself one by one:
vec = [MyClass(1), MyClass(2)];
list = vec.myfun();
classdef MyClass
properties
prop1
end
methods
function obj = MyClass(val)
obj.prop1 = val;
end
function val = myfun(obj)
if numel(obj) > 1
val = arrayfun(#(o) o.myfun(), obj);
return;
end
val = obj.prop1;
end
end
end
I have a csv file called Energy.csv and it's very simple:
Building A,150
Building B,160
I would like to import the csv into Ruby and print the second row, second column element (160). This is what I have so far but I don't know how to improve this code.
require 'csv'
class CSVImport
energyusageA = Array.new
energyusageB = Array.new
CSV.foreach('CSV/Energy.csv') do |row|
energyusageA = row[1]
energyusageB = row[2]
end
puts energyusageB[1]
end
To read this in quickly if it's a small file and memory isn't a constraint:
CSV.open('CSV/energy.csv').read[1][1]
Where that pulls the second row's second value as everything's zero-indexed in Ruby.
In your code you have it wrapped inside of a class definition but that doesn't really make sense unless you're defining methods. Yes you can run executable code there in that context but that's reserved for other situations like meta-progamming.
A Ruby-style design looks like this:
class CSVReader
def initialize(path)
#path = path
end
def value(row: 1, col: 1)
CSV.open(#path).read[row][col]
end
end
Where you can call it like:
CSVReader.new('CSV/energy.csv').value
CSVReader.new('CSV/energy.csv').value(row: 4, col: 2)
And so on.
I think you were quite close.
To get second row you can do it the following way:
require 'CSV'
second_row = Array.new
CSV.foreach('energy.csv') do | row |
second_row << row[1]
end
To get the second element you just need to access second column element (since ruby is 0-based it is 1):
second_row[1] will print you =>"160".
Edit I think I need to explain one more thing. The difference between = (assignment) and << (appending).
The = assigns the variable the right side.
The << appends the right side to the end of an Array.
You can try it out on the following test:
test = Array.new
test = 'Yo' => this assigns string to the test (*"Yo\n"* will be stored in the *test8 variable)
OR
test << 'Yo' => this appends to the empty array the string 'Yo' so the *Array* will look like this *["Yo"]*.
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("")
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