How to find which array element is not present in another - ruby

Here is the scenario
a = [1,2,3]
b = [2,5,6]
I would like to find out which elements of b are not present in a. I could use include? to check which ones are. But I am looking for something entirely opposite here.

> a - b
=> [1, 3]
> b - a
=> [5, 6]
(I can't quite tell which way you want to go.)

a = [1,2,3]
b = [2,5,6]
b - a #=> [5, 6]

Related

How to delete a element from two arrays independently which has been copied from one another?

a = [1,2,3]
=> [1, 2, 3]
b = a
=> [1, 2, 3]
b.delete(1)
=> 1
b
=> [2, 3]
a
=> [2, 3]
Array A has given [1,2,3] values, and Array A has been copied to Array B
Then whenever I delete a element from Array B , the element gets deleted from Array A too
eg : If i delete element 1 from array B ,it gets deleted from array A too..
How to avoid this, How to delete an element from these arrays separately ?
You can use dup to create a copy of the array.
a = [1,2,3]
=> [1, 2, 3]
b = a.dup
=> [1, 2, 3]
a.delete(1)
=> 1
a
=> [2, 3]
b
=> [1, 2, 3]
EDIT:
As to why this is, when you assign b = a, you assign b to be a reference to a. This means that both variables refer the same underlying object. With dup we are forcing Ruby to create a copy of a.
You are creating a shallow copy in b, so the contents aren't copied. To copy them, use Object::clone: b = a.clone.

Adding two arrays in Ruby when the array length will always be the same

So, I need to add two arrays together to populate a third. EG
a = [1,2,3,4]
b = [3,4,5,6]
so that:
c = [4,6,8,10]
I read the answer given here: https://stackoverflow.com/questions/12584585/adding-two-ruby-arrays
but I'm using the codecademy labs ruby editor and it's not working there, plus the lengths of my arrays are ALWAYS going to be equal. Also, I don't have any idea what the method ".with_index" is or does and I don't understand why it's necessary to use ".to_i" when the value is already an integer.
It seems like this should be really simple?
a = [1,2,3,4]
b = [3,4,5,6]
a.zip(b).map { |i,j| i+j } # => [4, 6, 8, 10]
Here
a.zip(b) # => [[1, 3], [2, 4], [3, 5], [4, 6]]
and map converts each 2-tuple to the sum of its elements.
OPTION 1:
For a pure Ruby solution, try the transpose method:
a = [1,2,3,4]
b = [3,4,5,6]
c = [a, b].transpose.map{|x, y| x + y}
#=> [4,6,8,10]
OPTION 2:
If you're in a Rails environment, you can utilize Rails' sum method:
[a, b].transpose.map{|x| x.sum}
#=> [4,6,8,10]
EXPLANATION:
transpose works perfectly for your scenario, since it raises an IndexError if the sub-arrays don't have the same length. From the docs:
Assumes that self is an array of arrays and transposes the rows and columns.
If the length of the subarrays don’t match, an IndexError is raised.

How to drop the end of an array in Ruby

Array#drop removes the first n elements of an array. What is a good way to remove the last m elements of an array? Alternately, what is a good way to keep the middle elements of an array (greater than n, less than m)?
This is exactly what Array#pop is for:
x = [1,2,3]
x.pop(2) # => [2,3]
x # => [1]
You can also use Array#slice method, e.g.:
[1,2,3,4,5,6].slice(1..4) # => [2, 3, 4, 5]
or
a = [1,2,3,4,5,6]
a.take 3 # => [1, 2, 3]
a.first 3 # => [1, 2, 3]
a.first a.size - 1 # to get rid of the last one
The most direct opposite of drop (drop the first n elements) would be take, which keeps the first n elements (there's also take_while which is analogous to drop_while).
Slice allows you to return a subset of the array either by specifying a range or an offset and a length. Array#[] behaves the same when passed a range as an argument or when passed 2 numbers
this will get rid of last n elements:
a = [1,2,3,4,5,6]
n = 4
p a[0, (a.size-n)]
#=> [1, 2]
n = 2
p a[0, (a.size-n)]
#=> [1, 2, 3, 4]
regard "middle" elements:
min, max = 2, 5
p a.select {|v| (min..max).include? v }
#=> [2, 3, 4, 5]
I wanted the return value to be the array without the dropped elements. I found a couple solutions here to be okay:
count = 2
[1, 2, 3, 4, 5].slice 0..-(count + 1) # => [1, 2, 3]
[1, 2, 3, 4, 5].tap { |a| a.pop count } # => [1, 2, 3]
But I found another solution to be more readable if the order of the array isn't important (in my case I was deleting files):
count = 2
[1, 2, 3, 4, 5].reverse.drop count # => [3, 2, 1]
You could tack another .reverse on there if you need to preserve order but I think I prefer the tap solution at that point.
You can achieve the same as Array#pop in a non destructive way, and without needing to know the lenght of the array:
a = [1, 2, 3, 4, 5, 6]
b = a[0..-2]
# => [1, 2, 3, 4, 5]
n = 3 # if we want drop the last n elements
c = a[0..-(n+1)]
# => [1, 2, 3]
Array#delete_at() is the simplest way to delete the last element of an array, as so
arr = [1,2,3,4,5,6]
arr.delete_at(-1)
p arr # => [1,2,3,4,5]
For deleting a segment, or segments, of an array use methods in the other answers.
You can also add some methods
class Array
# Using slice
def cut(n)
slice(0..-n-1)
end
# Using pop
def cut2(n)
dup.tap{|x| x.pop(n)}
end
# Using take
def cut3(n)
length - n >=0 ? take(length - n) : []
end
end
[1,2,3,4,5].cut(2)
=> [1, 2, 3]

Ruby Logical Operators - Elements in one but not both arrays

Let's say I have two arrays:
a = [1,2,3]
b = [1,2]
I want a logical operation to perform on both of these arrays that returns the elements that are not in both arrays (i.e. 3). Thanks!
Arrays in Ruby very conveniently overload some math and bitwise operators.
Elements that are in a, but not in b
a - b # [3]
Elements that are both in a and b
a & b # [1, 2]
Elements that are in a or b
a | b # [1, 2, 3]
Sum of arrays (concatenation)
a + b # [1, 2, 3, 1, 2]
You get the idea.
p (a | b) - (a & b) #=> [3]
Or use sets
require 'set'
a.to_set ^ b
There is a third way of looking at this solution, which directly answers the question and does not require the use of sets:
r = (a-b) | (b-a)
(a-b) will give you what is in array a but not b:
a-b
=> [3]
(b-a) will give you what is in array b but not a:
b-a
=> []
OR-ing the two array subtractions will give you final result of anything that is not in both arrays:
r = ab | ba
=> [3]
Another example might make this even more clear:
a = [1,2,3]
=> [1, 2, 3]
b = [2,3,4]
=> [2, 3, 4]
a-b
=> [1]
b-a
=> [4]
r = (a-b) | (b-a)
=> [1, 4]

Rails 3 - Remove items belonging to array B from array A

I'm starting to play with arrays, but i'm stuck with something that seems yet very simple...
I'm trying to remove x elements belonging to one array from another array.
I've looked at this but .... blocked :
Deleting items from an array requires multiple passes to remove them all
a = ["1","2","3","4","5","6"]
b = ["1","3"]
c = a.reject { |i| i =~ /b/ }
Well, i'm a bit lot here, thanks!
a = ["1","2","3","4","5","6"]
b = ["1","3"]
c = a - b
same as
c = a.reject{ |e| b.include? e }
If you want to modify an existing array by removing elements in another array you can use minus equals.
a = [1, 2, 3, 1, 4]
b = [1, 4]
a -= b
a
=> [2, 3]
Also keep in mind that subtracting an array of elements from another array will remove all occurrences of those elements not just the first occurrence.

Resources