Related
I have 2 arrays that I've zipped together and now I'm trying to swipe values at even positions.
So this is what I've tried:
a = [1, 2, 3, 4]
b = [111, 222, 333, 444]
c = a.zip(b)
# Now c is equal to: [[1, 111], [2, 222],[3, 333],[4, 444]]
c.map.with_index do |item, index|
a = item[0]
b = item[1]
if index%2 == 0
a, b = b, a
end
end
What I would like to have:
c = [[1, 111], [222,2], [3, 333],[444, 4]]
But it's still not working, is there a better solution ? Or how could I fix mine to make it work ?
EDIT:
I've realized that I could probably just use the ".reverse" method to swap the element. But I still can't manage to make it work.
Perhaps try:
c.map.with_index do |item, index|
index%2 != 0 ? item.reverse : item
end
=> [[1, 111], [222, 2], [3, 333], [444, 4]]
I would probably go with
a = [1, 2, 3, 4]
b = [111, 222, 333, 444]
a.zip(b).each_with_index do |item, idx|
item.reverse! if idx.odd?
end
#=>[[1, 111], [222, 2], [3, 333], [444, 4]]
zip as you did and reverse! just the items where the index is odd.
Other options include:
a.map.with_index(1) do |item,idx|
[item].insert(idx % 2, b[idx -1])
end
#=>[[1, 111], [222, 2], [3, 333], [444, 4]]
Here we use with_index starting with 1 and then use the modulo method to determine if the item in b should be placed at index 0 or index 1.
Or
a.zip(b).tap {|c| c.each_slice(2) {|_,b| b.reverse!}}
#=>[[1, 111], [222, 2], [3, 333], [444, 4]]
Here we zip a and b as your example did then we take the sub Arrays in groups of 2 and reverse the second Array using reverse! which will modify the Array in place.
I have two arrays like this: [[word],[number of occurence] , ... ]
Table 1 : [[["web"], 9], [["paris"], 8], [["html5"], 6], [["css3"], 6] ... ]
Table 2 : [[["web"], 2], [["paris"], 3], [["word"], 5], [["class"], 6] ... ]
I want to compare table 2 with table 1 and only show words NOT on table 2.
With the example I would have get:
Table 2 doesn't have html5, css3
Does Ruby have a gem that can do that?
The structure used here is quite irregular, but remapping it to something easier to work with isn't hard:
def hashify(list)
list.map do |(word), count|
[ word, count ]
end.to_h
end
The |(word), count| declaration pulls word out of the nested array, it simplifies the code.
Given sample data it works like this:
table1 = [[["web"], 9], [["paris"], 8], [["html5"], 6], [["css3"], 6] ]
table2 = [[["web"], 2], [["paris"], 3], [["word"], 5], [["class"], 6] ]
hashify(table1)
# => {"web"=>9, "paris"=>8, "html5"=>6, "css3"=>6}
Then you can use this to compute the difference:
hashify(table1).keys - hashify(table2).keys
# => ["html5", "css3"]
No need for any gem. Array difference works just fine, but you need to extract the interesting words first :
table1 = [[["web"], 9], [["paris"], 8], [["html5"], 6], [["css3"], 6]]
table2 = [[["web"], 2], [["paris"], 3], [["word"], 5], [["class"], 6]]
def extract_words(table)
table.map{|sub_array| sub_array.flatten.first }
end
puts extract_words(table1) - extract_words(table2)
# html5
# css3
With hashes, it would be easier :
hash1 = {"web"=>9, "paris"=>8, "html5"=>6, "css3"=>6}
hash2 = {"web"=>2, "paris"=>3, "word"=>5, "class"=>6}
puts hash1.keys - hash2.keys
# html5
# css3
I assume that you don't need the numerical data, so i would propose a one-line solution to your problem :
(table1.flatten - table2.flatten).reject {|elem| elem.is_a?(Integer)}
That returns the following array :
=> ["html5", "css3"]
table1 = [[["web"], 9], [["paris"], 8], [["html5"], 6], [["css3"], 6] ]
table2 = [[["web"], 2], [["paris"], 3], [["word"], 5], [["class"], 6] ]
table1.flat_map(&:first) - table2.flat_map(&:first)
# => ["html5", "css3"]
I have an array arr = [[1,2],[3,4]] and a column col = [5,6]
Is there an easy way to get an output of [[1,2,5],[3,4,6]] without looping? Thanks
Yes, using Array#transpose as follows:
arr = [[1,2],[3,4]]
col = [5,6]
pp (arr.transpose << col).transpose # => [[1, 2, 5], [3, 4, 6]]
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
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]