1

I am doing a challenge to make a method that finds duplicate values in an array, and prints out a new array without the duplicates. Ruby has a built in uniq method; however, I am not allowed to use it.

In my mind, this should work:

def uniques(array) 
  tempPos = 0
  arrayPos = 0
  duplicate = true
  result = [] # array the result will be "pushed" too
  for arrayPos in 0..array.length
    for tempPos in 0..array.length
      # If the values at the indexes are the same. But the indexes are not the same.
      # we have a duplicate
      if array[arrayPos] == array[tempPos] && arrayPos != tempPos
        duplicate = true
      else
        duplicate = false
      end
      if duplicate == false
        result[arrayPos] = array[arrayPos]
      end
    end
    puts duplicate
  end
  puts result.inspect
end

Output:

uniq *this is the short hand user input to run the method*
false
false
false
false
false
false
[1, 2, 1, 4, 5, nil]

I must be doing something wrong.

1
  • As an idea: sort_by(&:object_id) and then compare each value with the previous one to eliminate duplicates? Commented May 31, 2015 at 20:44

5 Answers 5

5

Are you allowed to use a Set?

require 'set'
array = [1, 2, 3, 3, 3, 4]

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

An other way is to iterate over every pair in the array:

array.each_cons(2).with_object([array.first]) do |pair, result| 
  result << pair.last unless pair.first == pair.last 
end
#=> [1, 2, 3, 4]
Sign up to request clarification or add additional context in comments.

2 Comments

The challenge didn't say I couldn't use 'set'... but they wanted it programmed out without the use of built in methods that would help complete the problem.
"...without the use of built in methods that would help complete the problem" seems to me an oxymoron. You're certainly going to have to use built-in methods, but if you find one that is helpful, I guess you can't use it. :-)
4

There are many ways to do that. Here's another. Suppose:

arr = [3,5,1,3,4,1,1]

Construct:

h = arr.group_by(&:itself)
  #=> {3=>[3, 3], 5=>[5], 1=>[1, 1, 1], 4=>[4]} 

The duplicates are given by:

h.select { |_,v| v.size > 1 }.keys
  #=> [3, 1]

and an array without the duplicates is given by:

h.keys
  #=> [3, 5, 1, 4] 

Comments

2

Your logic works fine altough as mentioned above a set would work better. You could also sort the elements, and then find adjacent pairs that are the same value which wouldn't work as well as a set, but would have slightly better run-time than your current solution:

To polish what you currently have:

def uniques(array) 
  result = [] # array the result will be "pushed" too

  for arrayPos in 0...array.length
    duplicate = false
    for tempPos in 0...result.length
      # if the values at the indexes are the same... but the indexes are not the same...
      # we have a duplicate
      duplicate ||= (array[arrayPos] == result[tempPos])
    end
    if !duplicate
      result << array[arrayPos]
    end
  end

  puts result
end

an slightly better approach (altought still poor performance):

def uniques(array) 
  result = [] # array the result will be "pushed" too

  for arrayPos in 0...array.length
    duplicate = result.include?(array[arrayPos])
    if !duplicate
      result << array[arrayPos]
    end
  end

  puts result
end

Although this solution is OK for a learning assignment, you should note that the complexity of this is O(n^2) (n-squared). What that means is that for an array of size n (for example n=10), you are doing n-squared (100) iterations.

It gets exponentially worse. If you have an array of length 1,000,000, you are doing 1,000,000,000,000 iterations. This is why using a set is so important, it's average run-time will be much lower.

9 Comments

I tested your code and it doesn't work? I do see how I can make it more concise though. I also know this isn't a good way to do it for functionality - it's just practice :)
The array is not necessarily sortable.
Complete brain-fart on my part. Updated the code using your style.
Well, your new code works... My one question; why does my current code NOT work?
That most likely has something to do with how you were incorrectly appending to the results array. Try doing result << array[arrayPos] with your original code. Also, make sure you use 3 dots ... in 0...array.length and 0...result.length
|
1

A fairly simple way to so this is to leverage array.include?

new = []
arr.each { |x| new << x unless new.include?(x)}
puts new

That will give you an array (new) that only includes unique elements from the original array (arr)

Comments

0

Duplicate array easy way

arr1 = [1,3,4,5,6,6,6,1] 

arry = Array.new(arr1)

puts arry

Find uniq array easy way using OR operator

arr1 = [1,3,4,5,6,6,6,1] 

arr2 = Array.new # creating new array

arry = arr1 | arr2 # compare two array using OR operator

puts arry

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.