# Nesting loops on same array but skipping same element

I'm having a bit of trouble trying to find a more Rubyist way to achieve the following. Essentially, I want to try and iterate over every element e and apply e.method(n) for every $n \in \text{array}$, $n \ne e$. In order to determine whether or not $n = e$, I'll have to use an index comparison (really just test for reference equality as opposed to functional equality).

arr = [413, 321, 654, 23, 11]
(0...arr.length).each do |outer_i|
(0...arr.length).each do |inner_i|
next if outer_i == inner_i
arr[outer_i].apply arr[inner_i]
end
end


This reeks of Java/C++ and I can tell that this is not the Ruby way, but I can't seem to find an alternative. Any ideas to improve its Ruby-ness? I was thinking of Array#product but I'm not sure where to go from there.

• Since appears to be off-topic for Code Review in its current state, since the code you've posted is pseudo-code. See if you can reword it to be more on-topic – Flambino Jul 20 '16 at 22:26
• @Flambino That's not pseudo code.. it will pass any Ruby interpreter (aside from the apply method) – Michael Jul 20 '16 at 22:28
• The apply call is my complaint, since the code doesn't run, nor is the function of that method made clear. Hence, the code felt incomplete to me. Pseudo-code like if you'd had a do_stuff method. However, re-reading your question, and seeing tokland's answer, I've retracted my close-vote. I felt there wasn't enough to go on, and misunderstood a few things, but I was wrong. – Flambino Jul 20 '16 at 22:35
• @Flambino Either way, thanks for pointing out the pseudo-code rule; wasn't aware of that! I'll try to steer clear of non-legal code in the future – Michael Jul 20 '16 at 22:40
• Did you patch the Fixnum class to define an apply method? That may be the most questionable practice in this code. – 200_success Jul 21 '16 at 1:32

Note that you are just doing a permutation of two elements from a set, and there is an abstraction in the core for that, Array#permutation(n):

arr.permutation(2).each { |x, y| x.apply(y) }

• Can't get much simpler than that! – Michael Jul 20 '16 at 22:41

Some remarks if you don't want to use the permutation-method.

The loop with a counter on an array is not rubyesk. In ruby an iterator like Array#each is preferred (I added the apply-method to the code to make it runnable):

class Fixnum
def apply(i)
puts "%i  -- %i " % [self,i]
end
end
arr = [413, 321, 654, 23, 11]

arr.each do |outer|
arr.each do |inner|
next if outer == inner
outer.apply inner
end
end


This works, unless the array contains an entry twice (e.g. arr = [413, 321, 654, 23, 11, 11]).

If you need the index you can use Array#.each_with_index:

arr.each_with_index do |outer, outer_i|
arr.each_with_index  do |inner, inner_i|
next if outer_i == inner_i
outer.apply inner
end
end


You may also replace the inner loop with an array without the element of the outer loop:

arr.each_with_index do |outer, outer_i|
arr2 = arr.dup #Without dup you would change the original array
arr2.delete_at(outer_i)
arr2.each  do |inner|
outer.apply inner
end
end