Вопрос

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?

Это было полезно?

Решение 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

Другие советы

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 }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top