0

For a challenge, I'm trying to return the unique values of an array without using uniq. This is what I have so far, which doesn't work:

def unique
   unique_arr = []
   input_arr.each do |word|
     if word != unique_arr.last
       unique_arr.push word
     end
   end
   puts unique_arr
end
input = gets.chomp
input_arr = input.split.sort
input_arr.unique

My reasoning here was that if I sorted the array first before I iterated through it with each, I could push it to unique_arr without repetition being a possibility considering if it's a duplicate, the last value pushed would match it.

Am I tackling this the wrong way?

7
  • Why are you reinventing the wheel? Personal exercise? Commented Feb 8, 2016 at 13:47
  • Yeah I'm only a beginner. I hadn't even heard of uniq until the challenge told me not to use it. Commented Feb 8, 2016 at 14:32
  • Your question was misleading. If it is meant to work only on a sorted array, then you should have written so, and not just implying that (subtlely) in the code. And you should note that that is different from what uniq does. Commented Feb 8, 2016 at 14:57
  • 1
    Or add the sort to the example code. Commented Feb 8, 2016 at 14:59
  • If you are going to apply split on input, what is the point of doing chomp? Commented Feb 8, 2016 at 14:59

6 Answers 6

4

Yes, you are making at least two mistakes.

  1. If you want to call it as input_arr.unique with input_arr being an array, then you have to define the method on Array. You have input_arr within your method body, which comes from nowhere.
  2. puts in the last line of your code outputs to the terminal, but makes the method return nil, which makes it behave differently from uniq.

It can be fixed as:

class Array
  def unique
    unique_arr = []
    each do |word|
      unique_arr.push(word) unless unique_arr.last == word
    end
    unique_arr
  end
end
Sign up to request clarification or add additional context in comments.

Comments

4

A unique array? That sounds like a Set to me:

require 'set'

Set.new([1,2,3,2,3,4]).to_a
#=> [1,2,3,4]

1 Comment

yea, Set is a perfect solution!
4

Here's a concise way to do it that doesn't explicitly use functionality from another class but probably otherwise misses the point of the challenge:

class Array
  def unique
    group_by(&:itself).keys
  end
end

Comments

0

I try this three options. Just for challenge

class Array
  def unique
    self.each_with_object({}) { |k, h| h[k] = k }.keys
  end

  def unique2
    self.each_with_object([]) { |k, a| a << k unless a.include?(k) }
  end

  def unique3
    arr = []
    self.map { |k| arr << k unless arr.include?(k) }
    arr
  end
end

3 Comments

In unique, what is the point of making the hash value (not the key) k? Won't a value like true suffice and be simpler?
In unique3, why are you explicitly writing self? What is the point of using map?
@sawa In unique I just try to show more ways to do this "challenge", ofc you are right with the true insted of k. In unique3 i use map bcs of more speed and like "new" way have uniq values.
0

Here is one more way to do this:

uniques = a.each.with_object([]) {|el, arr| arr << el if not arr.include?(el)}

Comments

-1

That's so easy if you see it this way:

a = [1,1,2,3,4]
h = Hash.new
a.each{|q| h[q] = q}
h.values

and this will return:

[1, 2, 3, 4]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.