I found another question on here that told how to get the matching items in 2 arrays like this:
matches = array1 & array2
However I have an array of arrays. like:
[[1,2,3,4],[2,3,4,5],[1,3,4,5]]
In this case I want to return 3 and 4 because they are in all three arrays.
How do I go about doing that?
Thank you!
Like this:
a.reduce(:&)
For example:
>> a = [[1,2,3,4],[2,3,4,5],[1,3,4,5]]
=> [[1, 2, 3, 4], [2, 3, 4, 5], [1, 3, 4, 5]]
>> a.reduce(:&)
=> [3, 4]
Related
This question already has answers here:
Ruby - collect same numbers from array into array of arrays
(4 answers)
Closed 2 years ago.
I have the array [1, 2, 2, 2, 3, 4, 4, 5, 6]
Is there any elegant way I can split it to sub-arrays, so that each array contains elements with same values?
I want to achieve the following result:
result = [[1], [2, 2, 2], [3], [4, 4], [5], [6]]
Thank you for your help !
Input
a = [1, 2, 2, 2, 3, 4, 4, 5, 6]
Code
p a.slice_when { |a, b| a != b }.to_a
output
[[1], [2, 2, 2], [3], [4, 4], [5], [6]]
Given an array A[] and a number x, check for pair in A[] with sum as x. can anyone help me out on this one in rails?
The ruby array #combination method can give you all combinations of array members of a given number of elements.
[1, 2, 3, 4, 5, 6].combination(2).to_a
=> [[1, 2], [1, 3], [1, 4], [1, 5], [1, 6], [2, 3], [2, 4], ... [5,6]]
Then you just want to select the elements where they add up to a given number.
[1, 2, 3, 4, 5, 6]combination(2).to_a.select{|comb| comb[0] + comb[1] == 7}
=> [[1, 6], [2, 5], [3, 4]]
To make it work for a different number of combined elements (e.g. 3 instead of 2) you can do...
[1, 2, 3, 4, 5, 6]combination(3).to_a.select{|c| (c.inject(0) {|sum,x| sum + x}) == 7}
This will work for 2, 3, 4, or any number up to the full array size.
It works by
finding combinations of 3
using `#inject' to sum all the elements of each combination
comparing that sum to the target number
You can easily achieve it by own function as:
def sum_as_x?(ary,x)
num=a.find{|e| ary.include?(x-e)}
unless num
puts "not exist"
else
p [x-num,num]
end
end
a = [1,2,3,4,5]
sum_to_x?(a,9)
>> [5, 4]
sum_to_x?(a,20)
>> not exist
I have two arrays of database records.
I'd like to add the second one to the beginning of the first.
I looked into insert, at a specific indexx, but it would result in inserting the second array inside the first one.
It might not be that hard, but thanks in advance for any help.
How is this Array#+ ?
array2 = [1,2,3]
array1 = [11,21]
array2 + array1
# => [1, 2, 3, 11, 21]
Ruby's splat to the rescue:
a = [1, 2, 3]
b = [4, 5, 6]
a.unshift(*b)
a #=> [4, 5, 6, 1, 2, 3]
I have an array of arrays like so: [[1, "dog"], [2, "cat"], [2, "bird"], [3, "monkey"]]. I want to check whether the larger array contains arrays of a given number without regard to the animal element of the array. I also do not want to loop through the array because this would become computationally heavy.
So something like #boolean = bigArray.include?([2, *]), except something that actually works...
You have two possible solutions. Detect the element in the array or convert the array into a Hash
1. Use Enumerable#detect, it will stop as soon as it finds a match and return it, nil otherwise.
> a = [[1, "dog"], [2, "cat"], [2, "bird"], [3, "monkey"]]
=> [[1, "dog"], [2, "cat"], [2, "bird"], [3, "monkey"]]
> a.detect{ |(n, _)| n == 2 }
=> [2, "cat"]
> a.detect{ |(n, _)| n == 10 }
=> nil
If you want to add this to the Array class like your example, and force it to return a boolean, do this:
class Array
def custom_include?(num)
!!detect{ |(n, _)| num == n }
end
end
Example:
> a.custom_include?(2)
=> true
> a.custom_include?(10)
=> false
2. If you don't care about the colliding keys, you could convert the array into a Hash and see if the key exists.
> a = [[1, "dog"], [2, "cat"], [2, "bird"], [3, "monkey"]]
=> [[1, "dog"], [2, "cat"], [2, "bird"], [3, "monkey"]]
> Hash[a][2]
=> "bird"
> Hash[a][10]
=> nil
One very simple way that doesn't involve looping is to convert the structure to a hash. Your arrays happen to be in an ideal format for this:
values = [[1, "dog"], [2, "cat"], [2, "bird"], [3, "monkey"]]
Hash[values][2] # "bird"
You will lose the first value for each key, but it will serve to show whether a key exists.
We can use this:
arr = [[1, "dog"], [2, "cat"], [2, "bird"], [3, "monkey"]]
arr.assoc(2)
it will return [2, cat]
in array if element is not exist
arr.assoc(10)
returns nil
I have two arrays:
a = [6, 4, 3]
b = [1, 3, 4]
I call a.sort:
a.sort = [3, 4, 6]
How do I sort array b so the values have the same position to values in array a before the sort?
It would be now:
b = [4, 3, 1]
So that values in b have the same position to values in array a.
You could combine both the arrays into one using the zip method. Once you combine a and b, you would get,
[[6, 1], [4, 3], [3, 4]]
Now sort the arrays, which would sort them based on the first element of each sub-array resulting in,
[[3, 4], [4, 3], [6, 1]]
Now we want to do the reverse of zip to get the first and second elements of each sub-array into a new array. Using transpose, we can get it back in the original form as,
[[3, 4, 6], [4, 3, 1]]
Thankfully using parallel assignment all of this is possible in one line. Here's the full code,
x, y = a.zip(b).sort.transpose
Now x should contain [3, 4, 6], and y should contain [4, 3, 1].
a = [6, 4, 3]
b = [1, 3, 4]
ra, rb = a.zip(b).sort_by(&:first).transpose
# ra => [3, 4, 6]
# rb => [4, 3, 1]
I don't know what you're trying to achieve, and I'm sure others could come up with a more elegant solution, but I would use a Hash instead. Assign the values of a a as the key, and the values of b as the values. You could iterate over a to accomplish this, or just in advance when you're creating this data. The result should be:
$ hash
=> {6 => 1, 4 => 3, 3 => 4}
a0 b0 a1 b1 a2 b2
$ hash.sort
=> [[3, 4], [4, 3], [6, 1]]
Like I said, not super smooth, but I've got turkey hangover...
[a, b].transpose.sort { |x, y| x[0] <=> y[0] }.transpose[1]
=> [4, 3, 1]
or
a, b = [a, b].transpose.sort { |x, y| x[0] <=> y[0] }.transpose