Pergunta

Let's say I want to get the first number inside an array which appears in it only once.

So, normally I would do it the following way:

arr = [1,1,2,2,3,4,4]
arr.detect { |elem| arr.count(elem) == 1 } # => 3

I've been wondering whether it is possible to obtain the array without needing to previously assign it to a variable, somehow like this:

[1,1,2,2,3,4,4].detect { |elem| self.count(elem) == 1 } # => NoMethodError

Which of course doesn't work, because self in the above is referring to Object.

So, is it possible to somehow refer to an object, on which enumerable method was called inside its block, like in the example above?

Foi útil?

Solução 2

I would use BasicObject#instance_eval :

Evaluates a string containing Ruby source code, or the given block, within the context of the receiver (obj). In order to set the context, the variable self is set to obj while the code is executing, giving the code access to obj’s instance variables. In the version of instance_eval that takes a String, the optional second and third parameters supply a filename and starting line number that are used when reporting compilation errors.

ary = [1,1,2,2,3,4,4]
ary.instance_eval do
  detect { |elem| count(elem) == 1 } # => 3
end

Outras dicas

Ha, that was interesting exercise, thanks for that:

module Enumerable
  def with_self
    return to_enum(:with_self) unless block_given?
    each do |element|
      yield element, self.entries
    end
  end
end

[1,1,2,2,3,4,4].detect.with_self { |elem, zelf| zelf.count(elem) == 1 }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top