1

The object of my coding exercise is to get rid of duplicates in an array without using the uniq method. Here is my code:

numbers = [1, 4, 2, 4, 3, 1, 5]

def my_uniq(array)
  sorted = array.sort
  count = 1
  while count <= sorted.length
    while true
      sorted.delete_if {|i| i = i + count}
      count += 1
    end
  end
  return sorted
end
  • When I run this, I get an infinite loop. What is wrong?
  • Can I use delete the way that I am doing with count?
  • How will it execute? Will count continue until the end of the array before the method iterates to the next index?
  • I did this with each or map, and got the same results. What is the best way to do this using each, delete_if, map, or a while loop (with a second loop that compares against the first one)?
5
  • 2
    I'm not sure why you have 2 while loops. The inner loop is what is infinite, because while count <= sorted.length never gets looked at. Commented Mar 5, 2015 at 22:30
  • Your question has been answered. Here's another way: numbers.each_with_object({}) { |n,h| h.update(n=>:anything) }.keys #=>[1, 4, 2, 3, 5] . This requires Ruby v1.9+, which keeps hash keys in insertion order. It relies on the fact that hashes have unique keys. Commented Mar 5, 2015 at 22:39
  • Thank you for your edit Cary. I am new to SO and am learning the "proper" ways to ask questions. I will try to keep my wording to a minimum ;) and thank you for your answer as well. Commented Mar 5, 2015 at 22:56
  • Your approach is not the best because the array is changing in size, but you keep incrementing the index count. Also, the block in sorted.delete_if {|i| i = i + count} refers to indexes, but you to compare values. Commented Mar 5, 2015 at 23:03
  • That exactly answers some of the concerns I had, but was unsure of! (I am also aware that '=' should be '=='). Thanks Cary! Commented Mar 5, 2015 at 23:44

6 Answers 6

4

Here is a clearly written example.

numbers = [1, 4, 2, 4, 3, 1, 5]

def remove_duplicates(array)
  response = Array.new
  array.each do |number|
     response << number unless response.include?(number)
  end
  return response
end

remove_duplicates(numbers)
Sign up to request clarification or add additional context in comments.

1 Comment

I love this answer as well because it is along the lines of one of my many attempts...except it actually works! at least I know my thought process was correct. Again, I would love to upvote this but I don't have the rep yet. Thanks for your input jBeas, it is very easy to see what is happening and another great example to learn from :)
2

As others pointed out, your inner loop is infinite. Here's a concise solution with no loops:

numbers.group_by{|n| n}.keys

You can sort it if you want, but this solution doesn't require it.

1 Comment

Thank you Mark! That is elegant! I don't have the rep yet (I'm a noob) to upvote your addition, or I would ;)
1

the problem is that the inner loop is an infinite loop:

while true
  sorted.delete_if {|i| i = i + count}
  count += 1
end #while

you can probably do what you are doing but it's not eliminating duplicates.

one way to do this would be:

numbers = [1, 4, 2, 4, 3, 1, 5]
target = []
numbers.each {|x| target << x unless target.include?(x) }
puts target.inspect

to add it to the array class:

class ::Array
    def my_uniq
       target = []
       self.each {|x| target << x unless target.include?(x) }
       target
    end
end

now you can do:

numbers = [1, 4, 2, 4, 3, 1, 5]
numbers.my_uniq

6 Comments

Thank you so much Mircea!!! Since i set my count to only go as far as array.length, why is it an infinite loop? is it the placement of the count iterator? I am playing with your solution now (which is easy to understand - much appreciated for that), as it needs to be a method, and it also needs to be added to the Array Class.
nope. it's the while true. that means execute while true is true which is forever
What I have done to it is this: numbers = [1, 4, 2, 4, 3, 1, 5] def my_uniq (array) target = [] array.each {|x| target << x unless target.include?(x) } end puts target.inspect but I get "undefined local variable or method 'target for main:Object ....so I am working on that! But again, thanks!!!
ahhhhhh! the while true! I am going to go back and try to make that work, just for sh!ts and giggles :)
updated to show how you would add your own method to the array class :)
|
1

You count use Set that acts like an array with does not allow duplicates:

require 'set'
numbers = [1, 4, 2, 4, 3, 1, 5]

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

2 Comments

@seinna you mean "I haven't heard of the Set class yet."
oops! true indeed jBeas
1

Try using Array#& passing the array itself as parameter:

x = [1,2,3,3,3]
x & x #=> [1,2,3]

Comments

0

This is one of the answer. However, I do not know how much of performance issue it takes to return unique

def my_uniq(ints)
    i = 0
    uniq = []

    while i < ints.length
        ints.each do |integers|
            if integers == i
                uniq.push(integers)
            end
            i += 1
        end
    end
    return uniq

end

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.