How to remove negative duplicates from an array?

How can I effectively remove negative duplicates of positive integers from an array of positive and negative integers, such as: [1, 5, 10, 5, -5, -1, 9] as a result, I want: [1, 5, 10, 5, 9] (-1 and -5 removed because they are negative duplicates 1 and 5)

+4
source share
5 answers

This is the easiest way to find:

  • select positive numbers
  • calculate their opposite number
  • remove them from the source array

array = [1, 5, 10, 5, -5, -1, 9]

p array - array.select{ |i| i > 0 }.map{ |i| -i }
# [1, 5, 10, 5, 9]

It uses Array#-that should be fast enough.

+6
source

O(n) , , , :

def reject_neg_dups(arr)
  positives = Hash[arr.map {|x| (x>0) ? [x,1] : nil }.compact]
  arr.reject { |x| (x < 0) && positives[-x] }
end

reject_neg_dups([-1, 1, 2, -2]) # => [1, 2]
reject_neg_dups([-1, 1, -2]) # => [1, -2] since 2 does not appear

, Array- , , :

require 'benchmark'

def reject_neg_dups_hash(arr)
  positives = Hash[arr.map {|x| (x>0) ? [x,1] : nil }.compact]
  arr.reject { |x| (x < 0) && positives[-x] }
end

def reject_neg_dups_include(arr)
  arr.reject { |x| (x < 0) && arr.include?(x.abs) }
end

def reject_neg_dups_arrayminus(arr)
  arr - arr.select { |i| i > 0 }.map { |i| -i }
end

def reject_neg_dups_arrayminusewo(arr)
  arr - arr.each_with_object([]) { |n,b| b << -n if n > 0 }
end

arr = Array.new(1000) { rand(-100..100) }
N = 1000
Benchmark.bm(15) do |x|
  x.report('Array-')    { N.times { reject_neg_dups_arrayminus(arr.dup) } }
  x.report('Array-ewo') { N.times { reject_neg_dups_arrayminusewo(arr.dup) } }
  x.report('hash')      { N.times { reject_neg_dups_hash(arr.dup) } }
  x.report('include?')  { N.times { reject_neg_dups_include(arr.dup) } }
end

:

                      user     system      total        real
Array-            0.180000   0.000000   0.180000 (  0.187512)
Array-ewo         0.200000   0.000000   0.200000 (  0.194663)
hash              0.250000   0.010000   0.260000 (  0.253355)
include?          3.660000   0.000000   3.660000 (  3.666313)
+5

, Array # reject:

>> a = [1, 5, 10, 5, -5, -1, 9]
>> a.reject { |e| e < 0 && a.include?(e.abs) }
=> [1, 5, 10, 5, 9]

, , :

>> b = [1, 5, 10, 5, -5, -1, 9, -15]
>> b.reject { |e| e < 0 && b.include?(e.abs) }
=> [1, 5, 10, 5, 9, -15]

:

def reject_negative_duplicates(array)
  array.reject { |e| e < 0 && array.include?(e.abs) }
end

>> reject_negative_duplicates(a)
=> [1, 5, 10, 5, 9]
>> reject_negative_duplicates(b)
=> [1, 5, 10, 5, 9, -15]

( ) :

class Array
  def reject_negative_duplicates
    self.reject { |e| e < 0 && self.include?(e.abs) }
  end
end

>> a.reject_negative_duplicates
=> [1, 5, 10, 5, 9]
>> b.reject_negative_duplicates
=> [1, 5, 10, 5, 9, -15]
+4
arr = [1, 5, 10, 0, 5, -5, -1, 9, -4]

arr - arr.each_with_object([]) { |n,b| b << -n if n > 0 }
  #=> [1, 5, 10, 0, 5, 9, -4] 
+3

Ruby uniq: https://ruby-doc.org/core-2.2.0/Array.html#method-i-uniq.

Otherwise, you will need to check the answer, for example this one , which describes how to build a structure to iterate through an array.

0
source

Source: https://habr.com/ru/post/1667680/


All Articles