Ruby array subtraction without removing items more than once
Subtract values as many times as they appear in the other array, or any Enumerable:
class Array
# Subtract each passed value once:
# %w(1 2 3 1).subtract_once %w(1 1 2) # => ["3"]
# [ 1, 1, 2, 2, 3, 3, 4, 5 ].subtract_once([ 1, 2, 4 ]) => [1, 2, 3, 3, 5]
# Time complexity of O(n + m)
def subtract_once(values)
counts = values.inject(Hash.new(0)) { |h, v| h[v] += 1; h }
reject { |e| counts[e] -= 1 unless counts[e].zero? }
end
Subtract each unique value once:
require 'set'
class Array
# Subtract each unique value once:
# %w(1 2 2).subtract_once_uniq %w(1 2 2) # => [2]
# Time complexity of O((n + m) * log m)
def subtract_once_uniq(values)
# note that set is implemented
values_set = Set.new values.to_a
reject { |e| values_set.delete(e) if values_set.include?(e) }
end
end
Subtract arrays with frequency
a1 = [1,2,2,2]
a2 = [1,2]
a2.each { |e| (idx = a1.find_index e) && (a1.delete_at idx) }
#⇒ [2, 2]
Here we iterate the second array and delete elements from the first one, once per iteration, if those were found.
The first found element will be deleted.
Subtracting one Array from another in Ruby
You can subtract arrays in Ruby:
[1,2,3,4,5] - [1,3,4] #=> [2,5]
ary - other_ary → new_ary Array Difference
Returns a new array that is a copy of the original array, removing any
items that also appear in other_ary. The order is preserved from the
original array.It compares elements using their hash and eql? methods for efficiency.
[ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ] #=> [ 3, 3, 5 ]
If you need
set-like behavior, see the library class Set.
See the Array documentation.
Remove common elements from two arrays while keeping duplicates in Ruby
a = [1,1,2,3,3,3,3]
b = [1,2]
a.each_with_index {|av,ai|
b.each_with_index {|bv,bi|
if (av == bv)
a[ai] = nil
b.delete_at(bi)
break
end
}
}
# a.compact!: [1,3,3,3,3]
For something a little more robust, see this answer:
https://stackoverflow.com/a/3852809/183181
Or here if order is important:
https://stackoverflow.com/a/21737172/183181
How to subtract values from one array with another ruby
.zip
only looks one level down. In your example x and y are not the values in the internal arrays, they're the internal arrays themselves. Subtracting one array from another removes all common elements from the first. That's why the result you see is first array with all zeros (common elements) removed.
If you want to zip the internal arrays, you need to go one level deeper:
values1.zip(values2).map { |x, y| x.zip(y).map { |a, b| a - b } }
Synchronizing two arrays
Here an implementation of TNT's elegant solution for deleting the first matching element of an array
class Array
def delete_first item
delete_at(index(item) || length)
end
def distinct other, own = self.dup
other.each{|e| own.delete_first(e)}
own
end
end
arr1.distinct arr2 # ["a", "a", "f"]
arr2.distinct arr1 # ["b", "d"]
How to find which items in a MASSIVE array appear more than once?
Does something like
items = 30_000_000
array = items.times.map do
rand(10_000_000)
end
puts "Done with seeding"
puts
puts "Checking what items appear more than once. Size: #{array.size}"
puts
t1 = Time.now
def more_than_once(array)
counts = Hash.new(0)
array.each do |item|
counts[item] += 1
end
counts.select do |_, count|
count > 1
end.keys
end
res = more_than_once(array)
t2 = Time.now
p res.size
puts "Took #{t2 - t1}"
work for you?
The duration is about 40s on my machine.
Ruby- Adding/subtracting elements from one array with another array
You could use zip:
a.zip(b).map { |x, y| y - x }
# => [1, 1, 1, 1]
There is also a Matrix class:
require "matrix"
a = Matrix[[1, 2, 3, 4]]
b = Matrix[[2, 3, 4, 5]]
c = b - a
# => Matrix[[1, 1, 1, 1]]
Related Topics
Ruby 1.9.2 and Rails 3 Cannot Open Rails Console
Why Doesn't My Cron Job Work Properly
Using God to Monitor Unicorn - Start Exited with Non-Zero Code = 1
How to Prompt for a Sudo Password Using Ruby
Method and Variable Name Is the Same
How to Use Double Brackets in a Regular Expression
Looping in a Spiral Outside-In
How to Check If a File Is Being Used by Other Application
How to Distinguish Xlsx and Docx Files from Zip Archives
Error: Mime-Types-Data Requires Ruby Version >= 2.0
Ruby on Rails: Advanced Search
Is There a Hook Similar to Class#Inherited That's Triggered Only After a Ruby Class Definition
Ruby Differences Between += and << to Concatenate a String
Split the String to Get Only the First 5 Characters
Best Practices for New Rails Deployments on Linux
Exporting an Environment Variable in Ruby