ruby on rails
i want to update the table Fruit in my database, using information stored in 2 arrays:
fruit_id=[2,8,14,35]
fruit_name=["apple","orange","banana","melon"]
so for example: Fruit.id 2 will have Fruit.name to be "apple"
i thought of for loop:
for i in fruit_id do
Fruit.find(i).update(name:fruit_name)
end
but that only made sense in my head....
i also apologize if this question had already been answered, im new to this and dont know the exact term to search for.... thanks alot!
Try something like this
fruit_id.zip(fruit_name).each do |id, name|
fruit = Fruit.find_by(id: id)
fruit.update_attribute(:name, name) if fruit
end
Here is a couple of hints I can suggest:
Use Array#zip
To reduce number of queries you can use ActiveRecord::Relation#where with ActiveRecord::Relation#update_all
So resulting code will be
fruit_ids = [2, 8, 14, 35]
fruit_names = ['apple', 'orange', 'banana', 'melon']
fruits = fruit_ids.zip(fruit_names) # => [[2, 'apple'], [8, 'orange'], [14, 'banana'], [35, 'mellon']]
fruits.each do |(id, name)|
Fruit.where(id: id).update_all(name: name)
end
Caution: update_all does not trigger validations, so if it's a case for you it's better to use initial approach with Fruit.find(id).update(name: name)
Related
So i have this Array of Hashes
{"id"=>50823, "code"=>"1PLAK", "name"=>"Eselente", "order"=>1}
{"id"=>74327, "code"=>"1MAGP", "name"=>"Mango", "order"=>2}
{"id"=>50366, "code"=>"1ANGC", "name"=>"Tabnie", "order"=>3}
{"id"=>76274, "code"=>"1FABD", "name"=>"Slamtab", "order"=>4}
And i want to select the field order (just one field at the same time) for comparing afterwards.
What's the correct way to do it?
Thanks!
When you only want to extract the values of the orders then I would do this:
array = [
{"id"=>50823, "code"=>"1PLAK", "name"=>"Eselente", "order"=>1},
{"id"=>74327, "code"=>"1MAGP", "name"=>"Mango", "order"=>2},
{"id"=>50366, "code"=>"1ANGC", "name"=>"Tabnie", "order"=>3},
{"id"=>76274, "code"=>"1FABD", "name"=>"Slamtab", "order"=>4},
]
array.map { |hash| hash["order"] }
#=> [1, 2, 3, 4]
When you are only interested in the very first value (1 like you wrote in the comments above) then you can do:
array.first["order"] # or array[0]["order"]
#=> 1
Suppose I have an array array = [1,2,3,4,5]
I want to collect all the elements and indices of the array in 2 separate arrays like
[[1,2,3,4,5], [0,1,2,3,4]]
How do I do this using a single Ruby collect statement?
I am trying to do it using this code
array.each_with_index.collect do |v,k|
# code
end
What should go in the code section to get the desired output?
Or even simpler:
[array, array.each_index.to_a]
I like the first answer that was posted a while ago. Don't know why the guy deleted it.
array.each_with_index.collect { |value, index| [value,index] }.transpose
Actually I am using an custom vector class on which I am calling the each_with_index method.
Here's one simple way:
array = [1,2,3,4,5]
indexes = *array.size.times
p [ array, indexes ]
# => [[1, 2, 3, 4, 5], [0, 1, 2, 3, 4]]
See it on repl.it: https://repl.it/FmWg
I want to build a new array starting from a hash with the following format:
HashConst = {[120,240] => 60, [240,480]=> 30} #Constant
I need to build a new array and assign as value to a new constant with the following format:
[ [[120,240] ,1], [[240,480], 1] ]
I tried :
NewArrayConst = HashConst.keys.each{ |res| [res, 1]}
but I get instead
[ [120,240], [240,480] ]
Only solution I found is the following:
tempVar = []
HashConst.keys.each_with_index{ |res,idx| tempVar [idx] = [res, 1]}
NewArrayConst = tempVar
Anyone knows a better solution to this and can explain why I cannot get the output I expect from NewArrayConst = HashConst.keys.each{ |res| [res, 1]}. I'm using 2.2.2-p95
Edit:
As many pointed out Hash var name is wrong and misleading, I have updated that to avoid confusion
You need to use map instead of each.
Array#each method does not return the result of the code executed in the block, but instead just returns the array on which each was called, which in your case is the value of hash.keys.
Array#map collects the values returned by block into an array.
hash = {[120,240] => 60, [240,480]=> 30}
p array = hash.keys.map{ |res| [res, 1]}
#=> [[[120, 240], 1], [[240, 480], 1]]
NOTE: Do not name your variable Hash as it is already a well-known class in Ruby. Use lower case hash if need be. Also, avoid camel case for variable names such as NewArrayConst, as Ruby recommends use of snake_case for naming variables - you can refer Ruby Style Guide for more details.
h = {[120,240] => 60, [240,480]=> 30}
val = 1
h.keys.product([val])
#=> [[[120, 240], 1], [[240, 480], 1]]
Have you tried Hash.to_a? Sometimes things are easier than you think.
I have a number like 12,345,678 and I'm trying to split it into an Array that's groups of 3. Such that if I have:
stack = 12345678
Then I could get the following Array:
overflow = [12,345,678]
I was thinking about using Enumberable#each_slice like another similar question asked here, but that creates a 2D array. So then I considered using Array#flatten but that wouldn't keep my numbers grouped properly.
Is there any nice way to do this, or is it going to be some nasty nested loop? Thx!
This may not be efficient, but it works. You can build on/optimize it.
stack.to_s.chars.reverse.each_slice(3).map {|s| s.reverse.join.to_i }.reverse
# => [12, 345, 678]
For pure Ruby way (Non-Rails):
number = 12345678
number.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse
#=> "12,345,678"
> number.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse.split(',').map(&:to_i)
#=> [12, 345, 678] # your expected output
If you want it in rails then there is very nice method number_with_delimiter
number_with_delimiter(12345678)
# => 12,345,678
Another option:
def break_in_3s(num)
return [0] if num.zero?
a = []
until num.zero?
num, last = num.divmod(1000)
a.unshift(last)
end
a
end
break_in_3s(12_345_678)
#=> [12, 345, 678]
break_in_3s(2_345_678)
#=> [2, 345, 678]
break_in_3s(312_345_678)
#=> [312, 345, 678]
I've assumed num is non-negative.
Aside: why don't we have:
class Array; alias >> unshift; end
so we could write:
a >> last
?
Suppose:
mentions=["2","1","3"]
unranked = User.where(:nickname.in => mentions).map
The output does not match the ordering in the provided array
output is random => 3, 1, 2
i want it as per the original array => 2, 1, 3
I had the same problem, I solved it like this:
mentions=["foo","bar","baz"]
ranked = User.where(:nickname.in => mentions).sort do |a, b|
mentions.index(a.nickname) <=> mentions.index(b.nickname)
end
Not really the most elegant solution since I'm sorting in the application and not on the database engine but hey.. it works (on small lists).