0

Let's say i have an array called teams.
I want to plan matches for every team with every other team.

This is almost what i want except that same matches are added twice:

teams.each do |red_team|
  teams.each do |blue_team|
    if red_team != blue_team
      @planned_matches << Match.new(red_team, blue_team)
    end
  end
end

How to do that?

3 Answers 3

8

In Ruby 1.8.7+ you can use Array#combination:

teams = %w(A B C D)
matches = teams.combination(2).to_a

In 1.8.6, you can use Facets to do the same:

require 'facets/array/combination'
# Same code as above.
Sign up to request clarification or add additional context in comments.

1 Comment

If only i knew how to install ruby 1.8.7+ on my fedora13 :)
2

check if it works

for i in 0..teams.length-1
  if i != teams.last
    for j in (i+1)..teams.length-1
      @planned_matches << Match.new(teams[i], teams[j])
    end
  end
end

EXAMPLE

teams = ['GERMANY', 'NETHERLAND', 'PARAGUAY', 'ARGENTINA']
for i in 0..teams.length-1
  if i != teams.last
    for j in (i+1)..teams.length-1
      puts " #{teams[i]}  Vs  #{teams[j]}"
    end
  end
end

O/P

 GERMANY  Vs  NETHERLAND
 GERMANY  Vs  PARAGUAY
 GERMANY  Vs  ARGENTINA
 NETHERLAND  Vs  PARAGUAY
 NETHERLAND  Vs  ARGENTINA
 PARAGUAY  Vs  ARGENTINA

3 Comments

The if statement doesn't do anything, i is an int and you are comparing it to a team name that is a String. But yeah, other than that, this is the best solution.
@Joshua :- oohhhhhhhhh yes i think it should be teams[i] != teams.last. I think it will work w/o if condition then. nocheck though.
You may want to use upto or ... or each_index. Also, for isn't idiosyncratic ruby.
0

In your class Match, assuming internal attributes are red and blue

class Match
#...
  def ==(anOther)
    red == anOther.blue and anOther.red == blue
  end
#...
end

and the loop :

teams.each do |red_team|
  teams.each do |blue_team|
    if red_team != blue_team
      new_match = Match.new(red_team, blue_team)
      planned_matches << new_match if !planned_matches.include?(new_match)
    end
  end
end

Explanation :

The include? function of Array uses the == methods, so you just have to override it and giving it the behaviour you want for your Matches.

5 Comments

This looks a bit better to me than solution by Salil. :)
@Arnis L :- performance wise it will iterate 16 times for array of length 4 where mine is iterate for just 7 times.
But real issue with this one is - i lose equality in case match.red == another.red && match.blue==another.blue.
This kind of iterating doesn't conform well to the Ruby way, but nonetheless, Salil's answer is a many many times more efficient. Also, the implementation of == in this answer is very questionable. For example, with that definition, an instance of Match is not equal to itself.
@Arnis iterating over collections rather than accessing them by index.

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.