how to concat string to array element in rails - ruby-on-rails

I have an array as
["first_name"]
and I want to convert it to
["user.first_name"]
I cannot figure out how I can do this in rails.

If you would like to append text to the values you have in a array you're going to probably want to loop through the data and append to each element in the array like so:
my_array = ["test", "test2", "first_name"]
new_array = my_array.collect{|value| "user.#{value}" }
new_array will now be:
["user.test", "user.test2", "user.first_name"]
You could also just overwrite your original array by using collect! like so
my_array = ["test", "test2", "first_name"]
my_array.collect!{|value| "user.#{value}" }
This will of course overwrite your original original data in my_array
If you would like to just change one value in the array you could use the index of that array and assign the value
my_array = ["test", "test2", "first_name"]
my_array[1] = "user.#{my_array[1]}}
my_array will now read:
["test", "user.test2", "first_name"]

Supposing you've multiple elements in your array, I recommend using .map.
It allows you to iterate the array elements, and return a new value for each of them.
%w[first_name last_name email].map do |attr|
"user.#{attr}"
end
# => [user.first_name, user.last_name, user.email]

Related

Array of Hashes push into another Array

I've an array contains hashes, I want to filter few parameters from the hash and insert the filtered data in another array but am not succeed below is the sample data I've used
a = Array.new
a = [
{"name"=>"hello", "age"=>"12", "sex"=> "M", "city"=>"Chennai"},
{"name"=>"name2", "age"=>"26", "sex"=> "M", "city"=>"Banglore"}
]
line_item = Array.new
hash_data = {}
a.each do |datas|
hash_data[:name] = datas["name"]
hash_data[:age] = datas["age"]
line_item << hash_data
end
I am getting this result:
[
{:name=>"name2", :age=>"26"},
{:name=>"name2", :age=>"26"}
]
But am expecting this:
[
{:name=>"hello", :age=>"12"},
{:name=>"name2", :age=>"26"}
]
Somebody please help to sort out this, Thanks in advance
Defining the hash outside the loop means that you keep adding the same hash object again (while overwriting its previous values). Instead, create a fresh hash within the loop:
line_items = []
a.each do |datas|
hash_data = {}
hash_data[:name] = datas["name"]
hash_data[:age] = datas["age"]
line_items << hash_data
end
The code looks a bit unidiomatic. Let's refactor it.
We can set the keys right within the hash literal:
line_items = []
a.each do |datas|
hash_data = { name: datas["name"], age: datas["age"] }
line_items << hash_data
end
We can get rid of the hash_data variable:
line_items = []
a.each do |datas|
line_items << { name: datas["name"], age: datas["age"] }
end
And we can use map to directly transform the array:
line_items = a.map { |h| { name: h["name"], age: h["age"] } }
#=> [{:name=>"hello", :age=>"12"}, {:name=>"name2", :age=>"26"}]
You can get the expected result with a combination of map and slice
a = [
{"name"=>"hello", "age"=>"12", "sex"=> "M", "city"=>"Chennai"},
{"name"=>"name2", "age"=>"26", "sex"=> "M", "city"=>"Banglore"}
]
a.map{ |e| e.slice("name", "age") }
#=> [{"name"=>"hello", "age"=>"12"}, {"name"=>"name2", "age"=>"26"}]
map: Returns Array containing the values returned by block
slice: Returns Hash including only the specified keys
In your loop you are essentially populating line_item with hash_data twice. This is the same object however. You can remedy this by using .dup.
a.each do |datas|
hash_data[:name]=datas["name"]
hash_data[:age]=datas["age"]
line_item << hash_data.dup # <- here
end
irb(main):044:0> line_item
=> [{:name=>"hello", :age=>"12"}, {:name=>"name2", :age=>"26"}]
Edit: I prefer rado's suggestion of moving your definition of hash_data inside the loop over using .dup. It solves the problem more than treating the symptom.
I think a lot of people are over complicating this.
You can achieve this using the following:
a.map { |hash| hash.select { |key, _value| key == 'name' || key == 'age' } }
If you want to return an array, you should nearly always be using map, and select simply selects the key - value pairs that match the criteria.
If you're set on having symbols as the keys, you can call symbolize_keys on the result.
I'll expand the code so it's a little more readable, but the one liner above works perfectly:
a.map do |hash|
hash.select do |key, _value|
key == 'name' || key == 'age'
end
end
On the first line hash_data[:name]=datas["name"] you are setting the key of the hash. That's why when the loop iterate again, it is overriding the value and after that push the new result to the hash.
One solution with reusing this code is just to put the hash_data = {} on the first line of your loop. This way you will have a brand new hash to work with on every iteration.
Also I would recommend you to read the docs about the Hash module. You will find more useful methods there.
If you want for all keys you can do this
array = [{"name"=>"hello", "age"=>"12", "sex"=> "M", "city"=>"Chennai"}, {"name"=>"name2", "age"=>"26""sex"=> "M", "city"=>"Banglore"}]
new_array = array.map{|b| b.inject({}){|array_obj,(k,v)| array_obj[k.to_sym] = v; array_obj}}
Ref: inject
Happy Coding

How can I get the value of the name only on this array?

This is the output array when I do
result = JSON.parse(response.body)
result.values.each {|element|
puts element
}
Result:
{"id"=>3, "code"=>"3", "name"=>"Market", "status"=>"A", "refcode"=>"001"}
{"id"=>4, "code"=>"4", "name"=>"Mall", "status"=>"A", "refcode"=>"002"}
From this array, I only want to get the name value. I tried this
puts result['data'][0]['name'] and it worked fine but I want to get all the name in the array
This is my expected output
Market
Mall
Try using Array#map and over each element, to access it's 'name' key, like:
p array.map { |element| element['name'] }
# ["Market", "Mall"]
I think it'd be something like:
result = JSON.parse(response.body)
result.values.map { |element| element['name'] }
# ["Market", "Mall"]
Since with each and puts you're only iterating and printing the hashes in the array, you could access the 'name' key from result.values.
I wont modify much. Since your name element is at position 3. access it like array because you are using values.each
result = JSON.parse(response.body)
result.values.each {|element|
puts element[2]
}

match key of hash and then fetch values accordingly in ruby

I have included the given code:
#classes = {1=>"USA", 3=>"France", 2=>"UK", 5=>"Europe", 7=>"Delhi", 8=>"test"}
#amaze = params[:test] #I get "1,3,7"
I get this, now please guide me how to match keys with #amaze and accordingly fetch its values from #classes i.e USA, France, Delhi.
Since #amaze is just a String, lets first convert it in Array so its easy to enumerate:
#amaze = "1,3,7"
#amaze = #amaze.split(",")
# => ["1", "3", "7"]
Now, since you have all keys extract all values:
#amaze.map { |i| #classes[i.to_i] }
# => ["USA", "France", "Delhi"]
Split #amaze by , and get an array of keys, convert them into Integer, then select only those key/value pairs which key is into this array of keys. Something like this:
#classes = {1=>"USA", 3=>"France", 2=>"UK", 5=>"Europe", 7=>"Delhi", 8=>"test"}
#amaze = "1,3,7" #I get "1,3,7"
arr = #amaze.split(',').map(&:to_i)
p #classes.select{|el| arr.include? el}
Result:
#> {1=>"USA", 3=>"France", 7=>"Delhi"}
If you want values only use .values:
p #classes.select{|el| arr.include? el}.values
Result:
#> ["USA", "France", "Delhi"]
For what(seemingly) you are asking, the below line will do it:
#amaze.split(",").each { |i| p #classes[i.to_i] }
# If #amaza = "1,3,7", above line will output:
# => "USA"
# "France"
# "UK"
This should work well for you:
#classes = {1=>"USA", 3=>"France", 2=>"UK", 5=>"Europe", 7=>"Delhi", 8=>"test"}
#amaze = params[:test].split(",").map(&:to_i)
#classes.values_at(*#amaze)
#=> ["USA", "France", "Delhi"]
Hash#values_at accepts an indefinite number of keys and returns their values as an array. The * (splat) operator explodes the array so this call actually becomes #classes.values_at(1,3,7) Docs
Might also want to add a compact to the end in the event a key does not exist. e.g
#amaze = params[:test].split(",").map(&:to_i) # Asssume this returns [1,3,7,9]
#classes.values_at(*#amaze)
#=> ["USA", "France", "Delhi",nil]
#classes.values_at(*#amaze).compact
#=> ["USA", "France", "Delhi"]
I think a clearer understanding of hashes would help you out here.
A Hash is a data structure that is a list of key-value pairs. For example, the following is a Hash object of key-value pairs (your example):
#classes = {1=>"USA", 3=>"France", 2=>"UK", 5=>"Europe", 7=>"Delhi", 8=>"test"}
If you want to extract a value from #classes, you need to pass the key of the value you want. If we wanted "USA" we would pass the key of 1 to #classes. If we wanted "France", we would pass it the key of 3:
#classes[1] would return "USA" and #classes[3] would return "France".
It's not clear what data structure #amaze is according to your question, but let's say it's the string "1, 3, 7" which we can split to create an array [1, 3, 7].
You could iterate over the array to get each of the values from #classes:
#amaze.split(",").map(&:to_i).each do |key|
puts #classes[key]
end
That would print out each of the corresponding values to keys in #classes.

Iterate over array of objects and concatenate their attributes which are arrays themselves

I have an array of objects that have an array as attribute. I want to concatenate these attributes. I'm doing this:
result = []
objects.each { |obj| result.concat(obj.attr) }
which works but looks bad. I tried
objects.reduce(:attr)
which does not work. It's a Rails app, and I want to concatenate related items into a single array. I want this:
[{
attr: [1,2]
},{
attr: [3,4]
}]
to turn into this:
[1,2,3,4]
You need to use Array#map :-
result = objects.map { |obj| obj.attr }
If you want the result array to be flattened :-
result = objects.flat_map { |obj| obj.attr }

How to insert an array to an existing hash array in Ruby?

I have a current array of the below hash map, i have another array that i would like to insert into each hash by matching on the id.
{"url"=>"http://ubuntu64:1990/getpages",
"id"=>"32794",
"version"=>"2",
"title"=>"Creating a page",
"space"=>"test",
"parentId"=>"32782",
"permissions"=>"0"}
The other array i want to add the 'imageurl' key/value based on the id, so something like (if id == id insert 'imageurl'/'someurl.jpg}
{"id"=>"32794", "imageurl" => "someurl.jpg}
array = [...] #Declare your array with the "big" hashes here
array2 = [...] #Declare your array with the hash containing the imageurl key here
array.each do |a|
array2.each do |a2|
if a[:id] == a2[:id]
a[:imageurl] = a2[:imageurl]
break #We found it
end
end
end
Should do the trick ... maybe there's a smarter way to do it though

Resources