开发者

why doesn't my refactored ruby using inject work?

I tried to do some refactoring to convert an each block into an inject, but it didn't work and I don't understand why.

Here's the code that works before refactoring:

class String
  # Build the word profile for the given word. The word profile is an array of
  # 26 integers -- each integer is a count of the number of times each letter
  # appears in the word. 
  #
  def profile
    profile = Array.new(26) { 0 }
    self.downcase.split(//).each do |letter|
      # only process letters a-z
      profile[letter.ord - 'a'.ord] += 1 unless letter.ord > 'z'.ord
    end
    profile开发者_StackOverflow
  end
end

and here's my refactor that doesn't work:

class String
  # Build the word profile for the given word. The word profile is an array of
  # 26 integers -- each integer is a count of the number of times each letter
  # appears in the word. 
  #
  def profile
    self.downcase.split(//).inject(Array.new(26) {0}) do |profile, letter|
      # only process letters a-z
      profile[letter.ord - 'a'.ord] += 1 unless letter.ord > 'z'.ord 
    end
  end
end

When I try and execute the refactored method I'm getting

`block in profile': undefined method `[]=' for 1:Fixnum (NoMethodError)

If I understand that correctly, it's doesn't like the array reference operator on the profile object in my refactored version, which implies that the initialiser passed to inject isn't working. Is that understanding correct? And if so, why not?

Thanks!


The []= method returns the assigned value, so the value of profile in the next iteration will be 1 (since it's the value of the last iteration). In order to get the behavior you want, you'll have to do:

self.downcase.split(//).inject(Array.new(26) {0}) do |profile, letter|
  # only process letters a-z
  profile[letter.ord - 'a'.ord] += 1 unless letter.ord > 'z'.ord 
  profile
end

or

self.downcase.split(//).inject(Array.new(26) {0}) do |profile, letter|
  # only process letters a-z
  profile.tap { profile[letter.ord - 'a'.ord] += 1 unless letter.ord > 'z'.ord }
end
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜