Reputation: 4976
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!
Upvotes: 0
Views: 4182
Reputation: 146231
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 }
Upvotes: 0
Reputation: 67900
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.
Upvotes: 0
Reputation: 124790
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.
Upvotes: 1