How can I shorten the following Ruby code? - ruby

I have an array of hashes, all with the same keys, all with a key of id. I need a comma delimited string of ids.
arr_widgets = []
widgets.each do |widget|
arr_widgets.push(widget['id'])
end
str_widgets = arr_widgets.join(',')

Have you tried something like this?
str_widgets = widgets.map { |w| w['id'] }.join(',')

There is no need to create an intermediate array.
widgets = [
{"id"=>"dec"}, {"id"=>21}, {"id"=>2020}, {"id"=>"was"},
{"id"=>"the"}, {"id"=>"shortest"}, {"id"=>"day"}, {"id"=>"of"},
{"id"=>"the"}, {"id"=>"longest"}, {"id"=>"year"}
]
Note that two values are integers.
s = widgets.each_with_object(String.new) do |widget, s|
s << ',' unless s.empty?
s << widget["id"].to_s
end
puts s
#=> "dec,21,2020,was,the,shortest,day,of,the,longest,year"

Related

Converting Ruby Hash into string with escapes

I have a Hash which needs to be converted in a String with escaped characters.
{name: "fakename"}
and should end up like this:
'name:\'fakename\'
I don't know how this type of string is called. Maybe there is an already existing method, which I simply don't know...
At the end I would do something like this:
name = {name: "fakename"}
metadata = {}
metadata['foo'] = 'bar'
"#{name} AND #{metadata}"
which ends up in that:
'name:\'fakename\' AND metadata[\'foo\']:\'bar\''
Context: This query a requirement to search Stripe API: https://stripe.com/docs/api/customers/search
If possible I would use Stripe's gem.
In case you can't use it, this piece of code extracted from the gem should help you encode the query parameters.
require 'cgi'
# Copied from here: https://github.com/stripe/stripe-ruby/blob/a06b1477e7c28f299222de454fa387e53bfd2c66/lib/stripe/util.rb
class Util
def self.flatten_params(params, parent_key = nil)
result = []
# do not sort the final output because arrays (and arrays of hashes
# especially) can be order sensitive, but do sort incoming parameters
params.each do |key, value|
calculated_key = parent_key ? "#{parent_key}[#{key}]" : key.to_s
if value.is_a?(Hash)
result += flatten_params(value, calculated_key)
elsif value.is_a?(Array)
result += flatten_params_array(value, calculated_key)
else
result << [calculated_key, value]
end
end
result
end
def self.flatten_params_array(value, calculated_key)
result = []
value.each_with_index do |elem, i|
if elem.is_a?(Hash)
result += flatten_params(elem, "#{calculated_key}[#{i}]")
elsif elem.is_a?(Array)
result += flatten_params_array(elem, calculated_key)
else
result << ["#{calculated_key}[#{i}]", elem]
end
end
result
end
def self.url_encode(key)
CGI.escape(key.to_s).
# Don't use strict form encoding by changing the square bracket control
# characters back to their literals. This is fine by the server, and
# makes these parameter strings easier to read.
gsub("%5B", "[").gsub("%5D", "]")
end
end
params = { name: 'fakename', metadata: { foo: 'bar' } }
Util.flatten_params(params).map { |k, v| "#{Util.url_encode(k)}=#{Util.url_encode(v)}" }.join("&")
I use it now with that string, which works... Quite straigt forward:
"email:\'#{email}\'"
email = "test#test.com"
key = "foo"
value = "bar"
["email:\'#{email}\'", "metadata[\'#{key}\']:\'#{value}\'"].join(" AND ")
=> "email:'test#test.com' AND metadata['foo']:'bar'"
which is accepted by Stripe API

how I could do a gsub with array elements?

How I could replaces a string like this
I think something like this
inputx.gsub(/variable1/,string1.split(";")[i])
But I dont know How I could do this code
name1;variable1
name;variable1
name3;variable1
by
dog;watch;rock
For obtain this
name1;dog
name;watch
name3;rock
string1 => dog;watch;rock ; this string Im trying to split for replace each string variable1
Please help me
subst = "dog;watch;rock".split ';'
input.gsub(/variable1/) do subst.shift end
#⇒ "name1;dog \n name;watch \n name3;rock"
Given (assuming) this input:
inputx = <<-EOD
name1;variable1
name;variable1
name3;variable1
EOD
#=> "name1;variable1\nname;variable1\nname3;variable1\n"
string1 = 'dog;watch;rock'
#=> "dog;watch;rock"
You can chain gsub and with_index to perform a replacement based on its index:
inputx.gsub('variable1').with_index { |_, i| string1.split(';')[i] }
#=> "name1;dog\nname;watch\nname3;rock\n"
You could also perform the split beforehand:
values = string1.split(';')
#=> ["dog", "watch", "rock"]
inputx.gsub('variable1').with_index { |_, i| values[i] }
#=> "name1;dog\nname;watch\nname3;rock\n"
I'm not sure there's a way to do it using .gsub(). One simple way to achieve what you want to is the following:
str = "dog;watch;rock"
array = str.split(";")
array.each_with_index do |str, i|
array[i] = "name#{i + 1};#{str}"
end
puts array
Output:
name1;dog
name2;watch
name3;rock
file intro2 => dog;watch;rock
file intro
name1;variable1
name;variable1
name3;variable1
ruby code
ruby -e ' n=0; input3= File.read("intro");string1= File.read("intro2") ;input3x=input3.gsub("variable1") { val =string1.split(";")[n].to_s; n+=1; val } ;print input3x' >gggf

Build list of substrings created by separating a string by a match

I have a string:
"a_b_c_d_e"
I would like to build a list of substrings that result from removing everything after a single "_" from the string. The resulting list would look like:
['a_b_c_d', 'a_b_c', 'a_b', 'a']
What is the most rubyish way to achieve this?
s = "a_b_c_d_e"
a = []
s.scan("_"){a << $`} #`
a # => ["a", "a_b", "a_b_c", "a_b_c_d"]
You can split the string on the underscore character into an Array. Then discard the last element of the array and collect the remaining elements in another array joined by underscores. Like this:
str = "a_b_c_d_e"
str_ary = str.split("_") # will yield ["a","b","c","d","e"]
str_ary.pop # throw out the last element in str_ary
result_ary = [] # an empty array where you will collect your results
until str_ary.empty?
result_ary << str_ary.join("_") #collect the remaining elements of str_ary joined by underscores
str_ary.pop
end
# result_ary = ["a_b_c_d","a_b_c","a_b","a"]
Hope this helps.
I am not sure about “most rubyish”, my solutions would be:
str = 'a_b_c_d_e'
(items = str.split('_')).map.with_index do |_, i|
items.take(i + 1).join('_')
end.reverse
########################################################
(items = str.split('_')).size.downto(1).map do |e|
items.take(e).join('_')
end
########################################################
str.split('_').inject([]) do |memo, l|
memo << [memo.last, l].compact.join('_')
end.reverse
########################################################
([items]*items.size).map.with_index(&:take).map do |e|
e.join('_')
end.reject(&:empty?).reverse
My fave:
([str]*str.count('_')).map.with_index do |s, i|
s[/\A([^_]+_){#{i + 1}}/][0...-1]
end.reverse
Ruby ships with a module for abbreviation.
require "abbrev"
puts ["a_b_c_d_e".tr("_","")].abbrev.keys[1..-1].map{|a| a.chars*"_"}
# => ["a_b_c_d", "a_b_c", "a_b", "a"]
It works on an Array with words - just one in this case. Most work is removing and re-placing the underscores.

split array element before . eg li.mean-array

I'm new to ruby i would like to know how can i split element containing special character.
I have the following array :
my_array = ["sh.please-word", ".things-to-do" , "#cool-stuff", "span.please-word-not"]
my_array.slice!(0..1)
puts my_array
=>#cool-stuff
=>span.please-word
i want it to split array elements that doesn't start with either a dot(.) or a (#) and return the list like this:
.please-word
.things-to-do
#cool_stuff
.please-word-not
i tried to use the slice method for a string which works perfectly, but when i try with the array element it doesn't work.
this is what i have done so far.
list_of_selectors = []
file = File.open("my.txt")
file.each_line do |line|
list_of_selectors << line.split(' {')[0] if line.start_with? '.' or line.start_with? '#'
end
while line = file.gets
puts line
end
i = 0
while i < list_of_selectors.length
puts "#{list_of_selectors[i]}"
i += 1
end
list = []
list_of_selectors.each { |x|
list.push(x.to_s.split(' '))
}
list_of_selectors = list
puts list_of_selectors
list_of_selectors.map! { |e| e[/[.#].*/]}
puts list_of_selectors
result_array = my_array.map { |x| x[/[.#].*/] }
# => [".please-word", ".things-to-do", "#cool-stuff", ".please-word-not"]
The above uses a regular expression to extract the text, beginning with either a dot(.) or a hashtag (#), and return it in the resulting array.

confused as to the behavior of this ruby fragment

Sorry to ask this but I really need to get this done. I'd like to be able to pass in a string and strip out the stop_words. I have the following:
class Query
def self.normalize term
stop_words=["a","big","array"]
term.downcase!
legit=[]
if !stop_words.include?(term)
legit << term
end
return legit
end
def self.check_parts term
term_parts=term.split(' ')
tmp_part=[]
term_parts.each do |part|
t=self.normalize part
tmp_part << t
end
return tmp_part
end
end
I would think that this would return only terms that are not in the stop_words list but I'm getting back either an empty array or an array of the terms passed in. Like this:
ruby-1.9.2-p290 :146 > Query.check_parts "here Is my Char"
=> [[], [], [], ["char"]]
ruby-1.9.2-p290 :147 >
What am I doing wrong?
thx in advance
If you just want to filter out the terms and get an array of downcased words, it is simple.
module Query
StopWords = %w[a big array]
def self.check_parts string; string.downcase.split(/\s+/) - StopWords end
end
Query.check_parts("here Is my Char") # => ["here", "is", "my", "char"]
Why do you want the result as an array I don't know but
term_parts=term.split(' ')
term_parts.reject { |part| stop_words.include?(part) }
You could write what you expect.
By the way, you have an array for array because
def self.check_parts term
term_parts=term.split(' ')
tmp_part=[] # creates an array
term_parts.each do |part|
t=self.normalize part # normalize returns an empty array
# or one of only one element (a term).
tmp_part << t # you add an array into the array
end
return tmp_part
end

Resources