Looping and creating an array in Ruby
Trying to port some old PHP code to Ruby and missing some key info on creating arrays in Ruby.
The PHP code:
foreach ($results as $r) {
$array[$r['column']][] = $r
}
Is this the simplest way to do it in Ruby? Do I have to initialize the second array?
@array = []
result.each do |r|
@array[r.cron_column] = []
@array[r.开发者_开发知识库cron_column] << r
end
I figure this is a simple syntax issue, but my Googling has turned up empty. Thanks for your help!
You are indexing into an empty array, so that will always return nil. nil does not define the << operator, so you get an error. You need to initialize the value at array[index] if you want to use the << operator.
I am assuming you want an array of arrays, so you can use this instead which will initialize the value at items[index] to an empty array if it is nil before pushing the value onto it
items = []
array.each do |r|
(items[r.column] ||= []) << r
end
The only change here is that, if items[r.column] returns nil it will be set equal to an empty array, otherwise nothing will be done. If you really just want to set the value at items[index] to r, just use the = operator.
Are you sure you need an array as output? it would appear a hash would be more convenient; moreover, it's way easier to build in your scenario (which is usually a sign you are in the correct path):
# example
results = [
OpenStruct.new(:x => 1, :cron_column => 0),
OpenStruct.new(:x => 2, :cron_column => 1),
OpenStruct.new(:x => 3, :cron_column => 1),
]
@array = results.group_by(&:cron_column)
# {0=>[#<OpenStruct x=1, cron_column=0>],
# 1=>[#<OpenStruct x=2, cron_column=1>, #<OpenStruct x=3, cron_column=1>]}
If cron_column "has no holes" (that's it, you have values from 0 to N), you can easily create an array with this same idea: results.group_by(&:cron_column).sort.map { |k, v| v }
or results.group_by(&:cron_column).sort.map(&:last)
, as you prefer.
array = results.inject([]) { |m, r| m[r.column] = r; m }
Update: oh, e1[] = e2
adds a new array element in PHP, so tokland is right, in which case:
array = results.inject([]) { |m, r| (m[r.column] ||= []) << r; m }
精彩评论