Small football table builder in Ruby Please review this small program I wrote to create a World Cup Group Table. You feed the program match info, and it builds a table based on that info.

  def table_for(matches)
    # Defaults that each team in the table should have
    defaults = { goals_for: 0, points: 0 }

    # Using the matches, let's create a hash for each team involved in a match
    teams = matches.each_with_object([]) do |match, array|
      array.push({ name: match[:home_team] }.merge!(defaults))
      array.push({ name: match[:away_team] }.merge!(defaults))
    end

    # We have 6 matches; each match involves 2 teams; we have 12 teams in our array.
    # Each team plays 3 matches, so we have 4 unique.
    teams.uniq

    # Loop through matches to build the table.
    matches.each do |match|

      # We only want to calculate data for matches that were played
      if match[:home_score].present? &amp;&amp; match[:away_score].present?

        # Grab the teams for this particular match from the list of teams
        home_team = teams.detect { |team| team[:name] == match[:home_team] }
        away_team = teams.detect { |team| team[:name] == match[:away_team] }

        # Compute goals_for
        home_team[:goals_for] += match[:home_score]
        away_team[:goals_for] += match[:away_score]

        # Home team wins
        if match[:home_score] &gt; match[:away_score]
          home_team[:points] += 3

        # Away team wins    
        elsif match[:home_score] &lt; match[:away_score]
          away_team[:points] += 3

        # It's a draw
        else
          home_team[:points] += 1
          away_team[:points] += 1
        end
      end
    end

    teams
  end


The rules are a win earns three points, a draw one point, a loss zero points.

For example, if we feed the method this match data:

[
  { id: 1, home_team: "Honduras", away_team: "Chile", home_score: 0, away_score: 1 },
  { id: 2, home_team: "Spain", away_team: "Switzerland", home_score: 0, away_score: 1 },
  { id: 3, home_team: "Chile", away_team: "Switzerland", home_score: 1, away_score: 0 },
  { id: 4, home_team: "Spain", away_team: "Honduras", home_score: 2, away_score: 0 },
  { id: 5, home_team: "Chile", away_team: "Spain", home_score: 1, away_score: 2 },
  { id: 6, home_team: "Honduras", away_team: "Switzerland", home_score: 0, away_score: 0 }
]


We should see this table:

| TEAM        | GF | POINTS |
| Spain       | 4  | 6      |
| Chile       | 3  | 6      |
| Switzerland | 1  | 4      |
| Honduras    | 0  | 0      |


How can I improve this? If there a better way to get the unique teams from the match info? That parts looks convoluted. I also feel that the method is too large.
Note that uniq is not in-place, uniq! is. Otherwise, I guess your code is pretty good if you like imperative style (maybe some unnecessary comments could be removed, though). Personally, I prefer a functional approach: less statements, more expressions. If you open a console and play with the input data, applying transformations, you'll see it's not as difficult as it would seem at first. In this case I'd write:

goals_cmp_to_points = {-1 =&gt; 0, 0 =&gt; 1, 1 =&gt; 3}
team_results = match_results.flat_map do |result|
  [[:home, :away], [:away, :home]].map do |side1, side2|
    goals_cmp = result[:"#{side1}_score"] &lt;=&gt; result[:"#{side2}_score"]
    {
      :team =&gt; result[:"#{side1}_team"],
      :goals =&gt; result[:"#{side1}_score"],
      :points =&gt; goals_cmp_to_points[goals_cmp],
    }
  end
end

#[{:team=&gt;"Honduras", :goals=&gt;0, :points=&gt;0},
# {:team=&gt;"Chile", :goals=&gt;1, :points=&gt;3},
# [...]
# {:team=&gt;"Switzerland", :goals=&gt;0, :points=&gt;1}]

table = team_results.group_by { |r| r[:team] }.map do |team, results_for_team|
  {
    :team =&gt; team, 
    :total_goals =&gt; results_for_team.map { |r| r[:goals] }.reduce(0, :+),
    :total_points =&gt; results_for_team.map { |r| r[:points] }.reduce(0, :+),
  }
end
sorted_table = table.sort_by { |tr| tr.values_at(:total_points, :total_goals) }.reverse

#[{:team=&gt;"Spain", :total_goals=&gt;4, :total_points=&gt;6},
# {:team=&gt;"Chile", :total_goals=&gt;3, :total_points=&gt;6},
# {:team=&gt;"Switzerland", :total_goals=&gt;1, :total_points=&gt;4},
# {:team=&gt;"Honduras", :total_goals=&gt;0, :total_points=&gt;1}]