0

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!

1
  • Are these arrays or hashes, or hashes of arrays? What is r.column, and what is the desired result? Commented Jan 15, 2011 at 22:23

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks Ed! I figured there was a shorter way to do it.
No problem. It is not equivalent to your sample code though. Your snippet will wipe out the current value at items[r.column] each time, while mine will initialize only if it is nil and then append the value.
0

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.

Comments

0
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 }

1 Comment

I think the OP wants to accumulate values in an array, not just override with the last one.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.