-1

I added my own method to the Array class that does the same thing as Array#uniq.

This is my version:

arr = ["fun", "sun", 3, 5, 5, 5, 1, 2, 1, "fun"]

class Array
    def my_uniq
        new_arr = []
        each do |item|
            new_arr << item unless new_arr.include?(item)
        end
        new_arr
    end
end

print arr.my_uniq

Is there a way to modify this to return the indices of the unique elements rather than the elements themselves?

Thrynn
  • 199
  • 2
  • 2
  • 11
  • I suggest you edit your question. 1. Your method definition for `my_uniq` is irrelevant, so remove it (Sorry.) 2. Replace the second sentence with something more precise, such as, "How can I write an `Array` method that returns the (smallest) index of each unique element of an array?" (Bold font unnecessary.) 3. Delete your third sentence. (Sadly, nobody cares.). 4. Give an example that retains your input (`arr = ["fun",...]`) and provides your desired or expected output ( `[0, 1, 2, 3, 6, 7]` if my understanding is correct). – Cary Swoveland Nov 13 '15 at 18:18
  • When you give an example, it is helpful to assign a variable to each input, as you have done (`arr = ....`). That way, readers can refer to those variables in answers and comments without having to define them. Lastly, the Ruby convention is to use snake_case for the names of variables and methods (e.g., `new_arr` rather than `newArr`). You don't have to do that, but if you don't, be warned, readers of your code may assume you are a newbie. – Cary Swoveland Nov 13 '15 at 18:31
  • Thanks for the tips. I'll update and read up on Ruby style. – Thrynn Nov 13 '15 at 18:41
  • On second thought, please disregard my suggestion #1; just make it clear that it's your code for `Array#uniq` and that you are trying to modify it to return an array of the indices of the unique elements. – Cary Swoveland Nov 13 '15 at 18:43
  • One more suggestion concerning your revision: move your second sentence to follow the code, and say something like "Is there a way to modify this to return the indices of the unique elements rather than the elements themselves? For the given value of `arr`, I would like it to return the array `[0, 1, 2, 3, 6, 7]`". I'll delete this comment once you've seen it. No reply req'd. – Cary Swoveland Nov 13 '15 at 18:50

2 Answers2

0

each_with_index will allow you to iterate your array and return indexes.

each_with_index do |item, index|
  newArr << index unless newArr.include?(item)
end
Gavin Miller
  • 43,168
  • 21
  • 122
  • 188
0
class Array
  def indices_uniq
    uniq.map { |e| index(e) }
  end
end

arr = ["fun", "sun", 3, 5, 5, 5, 1, 2, 1, "fun"]
arr.indices_uniq
  #=> [0, 1, 2, 3, 6, 7] 

To see what's going on here, let's write this more verbosely and include some code to display intermediate values:

class Array
  def indices_uniq
    puts "self = #{self}"
    arr = self
    u = arr.uniq
    puts "u = #{u}"
    u.map { |e|
      puts "#{e} is at index #{index(e)}"
      arr.index(e) }
  end
end

arr.indices_uniq
  # self = ["fun", "sun", 3, 5, 5, 5, 1, 2, 1, "fun"]
  # u = ["fun", "sun", 3, 5, 1, 2]
  # fun is at index 0
  # sun is at index 1
  # 3 is at index 2
  # 5 is at index 3
  # 1 is at index 6
  # 2 is at index 7
  #=> [0, 1, 2, 3, 6, 7] 

We can substitute out u and arr:

class Array
  def indices_uniq
    self.uniq.map { |e| self.index(e) }
  end
end

arr.indices_uniq
   #=> [0, 1, 2, 3, 6, 7]

The key: self is the receiver for methods that do not have explicit receivers. In the last version of the methods uniq and include both have the explicit receiver self. It follows that if the explicit receiver is removed, the receiver will still be self:

class Array
  def indices_uniq
    uniq.map { |e| index(e) }
  end
end

arr.indices_uniq
   #=> [0, 1, 2, 3, 6, 7]

Another way of doing this is to change the operative line to:

map { |e| index(e) }.uniq
Cary Swoveland
  • 106,649
  • 6
  • 63
  • 100