facets icon indicating copy to clipboard operation
facets copied to clipboard

Array#relative_index

Open trans opened this issue 11 years ago • 1 comments

One of Sean's extensions is:

class Array
  # Get the index of the first matching element relative to another index in an
  # array.  Starts counting from the anchor index (which has index 0 in the
  # array slice used for the Array#index call).  Like Array#index, may take a
  # block or a value.
  #
  #    %w[ a b c d e f g ].relative_index(4, :f)  # => 1

  def relative_index(anchor, val=nil, &block)
    subarray = self[anchor..-1]
    val ? subarray.index(val) : subarray.index(&block)
  end
end

I made an issue for this b/c I don't see this particular definition being so useful. It's much clearer just to do the a[anchor..-1].index(foo) one's self. However maybe a more liberal definition could be more useful.

  def relative_index(target, relative_to)
    i = (Integer === target ? target : index(target))
    return nil unless i
    j = (Integer === relative_to ? relative_to : index(relative_to))
    return nil unless j
    j - i
  end

This covers much of the same use case but can go further by supporting indexes or objects and can provide a negative index.

One problem though, what if the objects of the array are integers?

trans avatar Jan 29 '14 15:01 trans

I think your criticism is correct. I'd modify your suggestion to solve the integer element problem by allowing the method to take a block:

def relative_index(value, target=nil, &block)
  anchor = block ? index(&block) : (target.is_a?(Integer) ? target : index(target))
  return nil unless anchor
  self[anchor..-1].index(value)
end

This way, if you want to match an integer value, you can use a block to do so.

smackesey avatar Jan 29 '14 20:01 smackesey