-1

forgive me I see that this question has been asked in many ways here on forums but none have output the desired output and I have been stuck for a few days reading different explanations of how the inject method works. Could my code be inspected and seen where or what it that I'm doing wrong or lacking? I'm learning the language and don't want to get frustrated over my inexperience.

my code:


  def my_inject(initial = nil, sym = nil, &block)
    check = initial.nil?
    acc = check ? 0 : 1


    if block_given?
      my_each { |x| acc = yield(acc, x) }
      end
    acc
  end
alias_method :my_reduce, :my_inject

i have been testing with the test cases from ruby_doc.org. the test cases:

# Sum some numbers
(5..10).reduce(:+)                             #=> 45
# Same using a block and inject
(5..10).inject { |sum, n| sum + n }            #=> 45
# Multiply some numbers
(5..10).reduce(1, :*)                          #=> 151200
# Same using a block
(5..10).inject(1) { |product, n| product * n } #=> 151200
# find the longest word
longest = %w{ cat sheep bear }.inject do |memo, word|
   memo.length > word.length ? memo : word
end
longest                                        #=> "sheep"

My code works with all that has a block except the last one that returns sheep. An insight into what I'm doing wrong is much appreciated.

ok this is what i have now:

  def my_inject(initial = nil, sym = nil, &block)
    acc = initial.nil? ? 0 : 1
    sym ||= initial if initial.is_a? Symbol
    if !block_given?
      block = sym.to_proc
      my_each { |x| acc = block.call(acc, x) }
    else
      my_each { |x| acc = yield(acc, x) }
      end
    acc
  end
  alias_method :my_reduce, :my_inject

it works with the first four test cases, but not the 5th, also the first test case returns 46 instead of 45 which it's because of the check that I used but I've tried others that didn't work

aulbytj
  • 61
  • 8
  • _ except the last one that returns sheep._ - why "sheep" is a wrong result? – Fabio Mar 31 '20 at 22:29
  • no sheep is the right results but its like it skips it, it doesn't display any output for the longest – aulbytj Mar 31 '20 at 23:26
  • You aren't ever using `sym` in your method, that's why only the block-form works. Also, with `(5..10).reduce(:+) ` the `:+` would be interpreted as the first argument `initial`. I'm not sure how the actual `reduce` method handles this, but maybe it does a type check to see if the first argument is a symbol? – max pleaner Apr 01 '20 at 00:41
  • @maxpleaner I was unsure of how to implement it for ` sym ` I'm guessing I would need to check if `initial.nil? && !sym.nil?` `initial = sym` but then how would i implement the iterator without a block given. For `reduce` from what I have read `reduce` is an alias to `inject` – aulbytj Apr 01 '20 at 00:53
  • `initial.nil? && !sym.nil?` this wouldn't work, because like I said the `:+` would be interpreted as the value for `initial`. Rather you could use `sym ||= initial if initial.is_a?(Symbol)`. In terms of how to use `sym` in the method, you can do `acc.send(sym, x)`. – max pleaner Apr 01 '20 at 02:27
  • @maxpleaner check if there's a block: no block -> the sole argument is `sym` and the first element in the enumerable becomes your initial, with a block the sole argument is `initial` – Simple Lime Apr 01 '20 at 02:44
  • and then to use it, I'd go `block = sym.to_proc unless block_given?; my_each { acc = block.call(acc, x) }` (untested, treat as psuedo code) to avoid if/else-s everywhere – Simple Lime Apr 01 '20 at 02:58
  • I modified my code and now it works with the first four test cases, but not the 5th, also the first test case returns 46 instead of 45 which it's because of the check that I used but I've tried others that didn't work – aulbytj Apr 01 '20 at 15:28

1 Answers1

0

I was able to solve it with code.

 def my_inject(initial = nil, second = nil)
    arr = is_a?(Array) ? self : to_a
    sym = initial if initial.is_a?(Symbol) || initial.is_a?(String)
    acc = initial if initial.is_a? Integer

    if initial.is_a?(Integer)
      sym = second if second.is_a?(Symbol) || second.is_a?(String)
    end

    if sym
      arr.my_each { |x| acc = acc ? acc.send(sym, x) : x }
    elsif block_given?
      arr.my_each { |x| acc = acc ? yield(acc, x) : x }
    end
    acc
  end
  alias my_reduce my_injec
aulbytj
  • 61
  • 8