Lior Elrom
Lior Elrom

Reputation: 20862

How to correctly use the inject method in Ruby

I'm still a ruby newbie and I'm trying to learn how exactly to use the inject method.

By using the inject method, I'm trying to return an array of letters and their appearance in a given string like so:

def sorting(str)
  str.split("").uniq.map { |letter|
    [letter, str.split("").inject(0) { |sum, char| sum + 1 if letter == char }]
  }
end

p sorting("aaabdbbcccaaabcacba")

The desire result should be:

[["a", 8], ["b", 5], ["d", 1], ["c", 5]]

Unfortunately, I'm getting an error: undefined method '+' for nil:NilClass.

What am I doing wrong and how can I solve it using inject and its sum advantages?

Upvotes: 3

Views: 1970

Answers (2)

falsetru
falsetru

Reputation: 369084

using Enumerable#group_by seems more appropriate:

>> "aaabdbbcccaaabcacba".chars.group_by { |x| x }.map { |key, a| [key, a.size] }
=> [["a", 8], ["b", 5], ["d", 1], ["c", 5]]

Problem of the given code:

The block passed to inject does not care about non-matching character.

Replace sum + 1 if letter == char with letter == char ? sum + 1 : sum:

def sorting(str)
    str.split("").uniq.map { |letter|
        [letter, str.split("").inject(0) { |sum, char| letter == char ? sum + 1 : sum }]
    }
end

Upvotes: 7

Arup Rakshit
Arup Rakshit

Reputation: 118271

Here is another way to go :

s = "aaabdbbcccaaabcacba"
s.chars.uniq.map{|c|[c,s.count(c)]}
# => [["a", 8], ["b", 5], ["d", 1], ["c", 5]]

Upvotes: 1

Related Questions