1
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ 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 \$\endgroup\$ – Flambino Jul 20 '16 at 22:26
  • 1
    \$\begingroup\$ @Flambino That's not pseudo code.. it will pass any Ruby interpreter (aside from the apply method) \$\endgroup\$ – Michael Jul 20 '16 at 22:28
  • 1
    \$\begingroup\$ 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. \$\endgroup\$ – Flambino Jul 20 '16 at 22:35
  • 1
    \$\begingroup\$ @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 \$\endgroup\$ – Michael Jul 20 '16 at 22:40
  • \$\begingroup\$ Did you patch the Fixnum class to define an apply method? That may be the most questionable practice in this code. \$\endgroup\$ – 200_success Jul 21 '16 at 1:32
4
\$\begingroup\$

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) }
\$\endgroup\$
  • \$\begingroup\$ Can't get much simpler than that! \$\endgroup\$ – Michael Jul 20 '16 at 22:41
0
\$\begingroup\$

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      
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.