How can I iterate over array elements matching a regular expression? - ruby-on-rails

Is there a method that can be used with "each" to filter array elements depending on a regular expression matching?
I have for example the following array:
arr = ["one", "has_two", "has_tree", "four"]
I want to loop into this array and to take only elements beginning with "has".
the following code is doing the loop for all the elements
arr.each |element| do
....
end

You can use Enumerable's grep method to do this:
arr.grep(/^has/).each do |element|
...
end

You can select the elements you're interested in, and then loop over those:
arr.select { |e| e[/^has/] }.each do |element|
end

I'd say:
arr.find_all{|el| el =~ /^has/}.each do...

Related

Ruby : Wrap Double Quotes With Single Quotes

I've searched everywhere in SO and no lucks. Basically, i have this kind of array :
["a", "b", "c"]
I need to wrap this double quotes with single quotes to be like this :
['"a"', '"b"', '"c"']
The main reason for why i need to wrap this array element is because i need to query jsonb object in my database (PostgreSQL). The sample of query is like this :
data -> '#{af.column}' #> any(array#{#arr}::jsonb[])
To query jsonb object i need to put single quotes for each element.
UPDATE
Why i need to do this ? Its because, i need to combine multiple query into an array. Below is my example codes :
#conditions = args[:conditions] unless !args[:conditions].present?
#tables = ["assigned_contact"]
#query = self.joins({:assigned_contact => :call_campaign_answers})
.where(#conditions.join(" AND "))
.where("(data->>'age')::int between ? and ?", args[:min_age].to_i, args[:max_age].to_i)
.where("data -> 'gender' #> any(array[?]::jsonb[])", args[:gender].map(&:to_json))
.where("call_campaign_answers.answer IN (?)", args[:answers]).size
Where args[:conditions] are my query that i need to do wrape double quotes in single quotes.
If theres any other simple / method available, please let me know.
Assuming
ary = %w[a b c]
#=> ["a", "b", "c"]
Then
new_ary = ary.map {|el| %Q["#{el}"] }
produces exactly your desired output:
new_ary == ['"a"', '"b"', '"c"']
#=> true
The problem I see is you're not returning a single JSON array, but multiple independent arrays which could be a syntax error. Use a singular JSON value:
.where("data -> 'gender' #> any(array[?]::jsonb[])", args[:gender].to_json)

how to apply gsub on string elements within an array?

for example, I have an array which is structured as follow:
my_array = [["..\\..\\..\\Source\\file1.c"], ["..\\..\\..\\Source\\file2.c"]]
This array is produced by this code:
File.open(file_name) do |f|
f.each_line {|line|
if line =~ /<ClCompile Include="..\\/
my_array << line.scan(/".*.c"/)
end
}
end
Later in the code I'm working on the array:
my_array .each {|n| f.puts n.gsub(/\\/,"//")}
As you can see, would like to replace all the backslashes with forward slashes on the elements within the array. The elements presents paths to source files. On the end I will output these paths within an other file.
I get this error:
undefined method `gsub' for [["..\\..\\..\\Source\\file1.c"], ["..\\..\\..\\Source\\file2.c"]]:Array (NoMethodError)
Any idea?
You have an array of arrays, so if you want to keep it like that, you would need to have 2 loops.
Otherwise, if you change your variable to this: my_array = ["..\\..\\..\\Source\\file1.c", "..\\..\\..\\Source\\file2.c"] your code should work.
UPDATE
if you can not control my_array, and it is always an array of one item arrays, perhaps this is cleanest:
my_array.flatten.each {|n| puts n.gsub(/\\/,"//")}
What it does is transforms two-dimensional array in one-dimensional.
my_array.flatten.each { |n| f.puts n.tr('\\', '/') }
As others have pointed out, you are calling gsub on an array, not the string within it. You want:
my_array.each {|n| puts n[0].gsub(/\\/,"//")}

Comparing two arrays and not getting expected output in rails console

I have the following controller action that builds two arrays.
current_event = Event.find(params[:event_id])
campaign_titles = Relationship::CampaignTitleRelationship.where(campaign_id: current_event.campaign_id)
campaign_title_ids = Array.new
campaign_titles.each do |title|
campaign_title_ids << [title.title_id]
end
event_title_ids = Array.new
params[:title_ids].each do |title|
event_title_ids << [title]
end
The two arrays output like this
[["6556"], ["9359"], ["11319"], ["12952"], ["14389"], ["14955"], ["16823"]]
[[6556], [9359], [11319], [12952], [14389], [14955], [16823]]
I'm trying to compare these two arrays using the - symbol, but am only getting an output of each id, instead of what I expect (nothing) since both arrays contain the same items.
I can see that the first array has quotations around each key inside the bracket. The second does not. How do I compare these two arrays?
Just add params as integers to your array
params[:title_ids].each do |title|
event_title_ids << [title.to_i]
end

Building a hash or array in a helper method in rails 4

I am trying to build an array of hashes (I THINK that's the way I phrase it) with a helper method so that I can use it in my view. I am getting the 2 values from columns #other_events.time_start and #other_events.time_end.
helper.rb
def taken_times()
#taken_times = []
#other_events.each do |e|
#taken_times << { e.time_start.strftime("%l:%M %P") => e.time_end.strftime("%l:%M %P")}
end
#taken_times
end
What I am trying to have is an array of hashes like this:
['10:00am', '10:15am'],
['1:00pm', '2:15pm'],
['5:00pm', '5:15pm'],
which is essentially
['e.time_start', 'e.time_end'],
I think you should refactor your method to this:
def taken_times(other_events)
other_events.map { |event| [event.time_start, event.time_end] }
end
The helper method is not setting a global variable #taken_times anymore but you can easily call #taken_times = taken_times(other_events).
The helper method is using it's argument other_events and not on the global variable #other_events which could be nil in certain views.
The helper method returns an array of arrays, not an array of hashes. It is a two-dimensionnal array ("width" of 2, length of x where 0 ≤ x < +infinity).
The helper method returns an array of arrays containing DateTime objects, not String. You can easily manipulate the DateTime objects in order to format it in the way you want. "Why not directly transform the DateTime into nice-formatted strings?" you would ask, I would answer with "because you can do that in the view, at the last moment, and maybe someday you will want to do some calculation between the time_start and the time_end before rendering it.
Then in your view:
taken_times(#your_events).each do |taken_time|
"starts at: #{taken_time.first.strftime("%l:%M %P")}"
"ends at: #{taken_time.last.strftime("%l:%M %P")}"
end
You are asking for an array of hashes ([{}, {}, {}, ...]):
Array: []
Hash: {}
But you are expecting an array of array ([[], [], [] ...])
You should do something like this:
def taken_times()
#taken_times = []
#other_events.each do |e|
#taken_times << [e.time_start.strftime("%l:%M %P"), e.time_end.strftime("%l:%M %P")]
end
#taken_times
end

In Ruby, can I pass each element of an array individually to a method that accepts *args?

Given a method that returns an array and another accepts an arbitrary number of arguments, is there a way to call the second method with each element of the array as an argument?
For example:
def arr
["a", "b", "c"]
end
def bar(*args)
args.each {|a| puts a}
end
I want to call
bar "a", "b" , "c"
Of course this is a simplified example, in reality arr could return an array of any size (say if it's an ActiveRecord find, and I want to pass all the results to bar), hence my problem.
You can do this:
my_array = ['a', 'b', 'c']
bar(*my_array)
This will flatten out the array into it's individual elements and pass them to the method as separate arguments. You could do this to any kind of method, not only ones that accept *args.
So in your case:
bar *arr
Use * also when you give an array as an argument:
bar(*arr)

Resources