0

I've written this script to be run in PHP, and am trying to convert it to Ruby.

Code:

$cases = array();


foreach($results as $result)
{
    if(!array_key_exists($result['id'], $cases))
        $cases[$result['id']] = array($result);
    else
        $cases[$result['id']][] = $result;
}

foreach($cases as $key => $case)
{
    foreach($case as $payment)
    {
        if(count($case) > 1)
        {

            $cases[$key]['total'] += ($payment['p1'] > $payment['p2']) ? $payment['p1'] : $payment['p2'];

        } else {

            $cases[$key]['total'] = ($payment['p1'] > $payment['p2']) ? $payment['p1'] : $payment['p2'];
        }
    }
}

In Ruby, I have the results as an array returned by MySQL (using mysql2 gem). Using the loop below, it prints every row. How can I check if the key exists when it does not provide keys?

What's the best way to implement this code in Ruby? How can I add a hash onto a hash in Ruby similar to adding an array onto an array in PHP.

results.each(:as => :array) do |row|
    puts row.inspect
end

More explanation:

PHP Structure

Array(
    0 => Array(
        Array(
            [id] => 'random id',
            [p1] => 534,
            [p2] => 105
        ),
        Array(
            [id] => 'random id',
            [p1] => 335,
            [p2] => 425
        )
    ),
    1 => Array(
        Array(
            [id] => 'random id',
            [p1] => 259,
            [p2] => 124
        )
    )
)

And i'm trying to iterate over each array inside the first, and if p1 > p2, add p1 to the total key on that array. i.e., the 0 index would look like this:

0 => Array(
    'total' => 959,
    Array(
        [id] => 'random id',
        [p1] => 534,
        [p2] => 105
    ),
    Array(
        [id] => 'random id',
        [p1] => 335,
        [p2] => 425
    )
)

1 Answer 1

1

Are you trying to group by result['id']? I believe that "translating" your PHP code to ruby will look something like this:

cases = {}
results.each do |result|
  if cases[result['id']]
    cases[result['id']] << result
  else
    cases[result['id']] = [result]
  end
end

Another way to get the same result is to use group_by:

cases = results.group_by { |result| result['id'] }

The second part "translated" to ruby will look something like this:

cases.each do |key, c|
  c.each do |payment|
    if c.count > 1 
      c['total'] += (payment['p1'] > payment['p2']) ? payment['p1'] : payment['p2']
    else
      c['total'] = (payment['p1'] > payment['p2']) ? payment['p1'] : payment['p2']
    end
  end
end

(this will actually not work in ruby, since an array cannot have an arbitrary key like 'total' - it accepts only numbers in its brackets. You will have to modify this code to hold the totals in a different structure)

Again, a more idiomatic way of summing up the max between 'p1' and 'p2' of each payment in each case might look more like this:

totals = cases.values.map do |c|
  c.inject(0) { |sum, payment| sum + [payment['p1'], payment['p2']].max }
end
Sign up to request clarification or add additional context in comments.

2 Comments

That's only the first part.
@nmm59 - added the other part

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.