How can I effectively delete negative duplicates of positive integers from an array of positive and negative integers like this: [1, 5, 10, 5, -5, -1, 9] as a result, I want to have: [1, 5, 10, 5, 9] (-1 and -5 removed as they are negative duplicates of 1 and 5)
如何有效地从正整数和负整数数组中删除正整数的负重复,如下所示:[1,5,10,5,-5,-1,9]因此,我希望:[1, 5,10,5,9](-1和-5被删除,因为它们是1和5的负重复)
5 个解决方案
#1
6
This is the easiest method I could find :
这是我能找到的最简单的方法:
- select positive numbers
- 选择正数
- calculate their opposite number
- 计算他们的相反数字
- remove them from the original 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#-
, which should be reasonably fast.
它使用Array# - ,它应该相当快。
#2
5
You can do this in O(n)
with just two passes through the array by hashing the positive numbers then rejecting from the array negative values whose abs was hashed:
您可以在O(n)中执行此操作,只需两次遍历数组,然后对正数进行散列,然后从绝对值为abs的数组负值中拒绝:
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
Note interestingly that the Array-
solutions are considerably faster than others listed so far:
有趣的是,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
Example output:
输出示例:
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)
#3
4
You can do this easily using Array#reject:
您可以使用Array#reject轻松完成此操作:
>> a = [1, 5, 10, 5, -5, -1, 9]
>> a.reject { |e| e < 0 && a.include?(e.abs) }
=> [1, 5, 10, 5, 9]
To clarify with another example, this will not remove negative values that do not have a corresponding positive value in the array:
为了澄清另一个例子,这不会删除数组中没有相应正值的负值:
>> b = [1, 5, 10, 5, -5, -1, 9, -15]
>> b.reject { |e| e < 0 && b.include?(e.abs) }
=> [1, 5, 10, 5, 9, -15]
You can define a method like so:
你可以定义一个这样的方法:
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]
Or extend (monkey patch) Array:
或者扩展(猴子补丁)数组:
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
3
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]
#5
0
In Ruby you could use the uniq method: https://ruby-doc.org/core-2.2.0/Array.html#method-i-uniq.
在Ruby中,您可以使用uniq方法:https://ruby-doc.org/core-2.2.0/Array.html#method-i-uniq。
Otherwise, you'll want to check an answer like this one which covers how to build a structure to iterate through an array.
否则,你会想要检查一个这样的答案,其中包括如何构建一个迭代数组的结构。
#1
6
This is the easiest method I could find :
这是我能找到的最简单的方法:
- select positive numbers
- 选择正数
- calculate their opposite number
- 计算他们的相反数字
- remove them from the original 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#-
, which should be reasonably fast.
它使用Array# - ,它应该相当快。
#2
5
You can do this in O(n)
with just two passes through the array by hashing the positive numbers then rejecting from the array negative values whose abs was hashed:
您可以在O(n)中执行此操作,只需两次遍历数组,然后对正数进行散列,然后从绝对值为abs的数组负值中拒绝:
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
Note interestingly that the Array-
solutions are considerably faster than others listed so far:
有趣的是,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
Example output:
输出示例:
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)
#3
4
You can do this easily using Array#reject:
您可以使用Array#reject轻松完成此操作:
>> a = [1, 5, 10, 5, -5, -1, 9]
>> a.reject { |e| e < 0 && a.include?(e.abs) }
=> [1, 5, 10, 5, 9]
To clarify with another example, this will not remove negative values that do not have a corresponding positive value in the array:
为了澄清另一个例子,这不会删除数组中没有相应正值的负值:
>> b = [1, 5, 10, 5, -5, -1, 9, -15]
>> b.reject { |e| e < 0 && b.include?(e.abs) }
=> [1, 5, 10, 5, 9, -15]
You can define a method like so:
你可以定义一个这样的方法:
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]
Or extend (monkey patch) Array:
或者扩展(猴子补丁)数组:
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
3
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]
#5
0
In Ruby you could use the uniq method: https://ruby-doc.org/core-2.2.0/Array.html#method-i-uniq.
在Ruby中,您可以使用uniq方法:https://ruby-doc.org/core-2.2.0/Array.html#method-i-uniq。
Otherwise, you'll want to check an answer like this one which covers how to build a structure to iterate through an array.
否则,你会想要检查一个这样的答案,其中包括如何构建一个迭代数组的结构。