Ruby algorithm solving - arrays

So I have a basic problem that needs to be solved. I need to take the following nested array [1, 2, ["str", 1], [[2]]] and return [1,2,"str",1,2]. Ultimately removing all nested arrays. The following is my incomplete solution:
test = [1, 2, ["str", 1], [[2]]]
def remove_array(array)
new_array = []
array.each do |item|
if item != Array
puts "you are here"
new_array << item
else
remove_array(item)
end
end
end
remove_array(test)
This is a classic recursion method. However, I cant seem to think of how to maintain new_array. Every time I pass the item that is an array to it, new_array doesn't maintain its state. I would also like to point out that I am aware of the built in method flatten as I am trying to solve the solution without said method. Any advice would be greatly appreciated.

def my_flatten(arr)
result = []
arr.each do |el|
if el.is_a?(Array)
result.concat(my_flatten(el))
else
result << el
end
end
result
end
You generally had the right idea, but you were never adding the inner array elements into your result.

def remove_array(array)
new_array = []
array.each do |e|
if e.is_a?(Array)
new_array += remove_array(e)
else
new_array << e
end
end
new_array
end

You can call flatten on you array.
a = [1, 2, ["str", 1], [[2]]]
=> [1, 2, ["str", 1], [[2]]]
a.flatten
=> [1, 2, "str", 1, 2]

In Ruby, there is a convenient built-in method called flatten
It will "flatten" your array so that all the inside arrays disappear, and it returns one array with all elements inside
Edit:
Sorry editing this. Forgot that you were using recursion for your solution. Since you're essentially creating a new array each recursion, I'm not exactly sure how I would fix your solution at this moment.

just use the flatten! :) keep it simple..
test = [1, 2, ["str", 1], [[2]]]
def remove_array(array)
array.flatten!
return array
end
remove_array(test)
2.2.1 :024 > remove_array(test)
=> [1, 2, "str", 1, 2]
I hope this helps everybody! Thanks

Related

In Ruby, how do you square a numbers in an array? [duplicate]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
This is code I currently have
def square_array(array)
array.each do |i|
i ** 2
end
end
I know it's not correct, could someone explain this process to me please?
Using each and << with an empty array
def square_array(array)
arr = []
array.each { |i| arr << i ** 2 }
arr
end
my_arr = [1, 2]
p square_array(my_arr) #=> [1, 4]
Here we've created a new empty array arr. We then iterate through the other array array which is passed as an argument, squaring each element before pushing it (using <<) into our new array arr.
Finally we return the newly created array arr by simply writing arr as the final line in the method block. We could have written return arr but in Ruby the return keyword can be omitted.
Using each_with_object
A slight evolution of the above technique
def square_array(array)
array.each_with_object([]) { |i,arr| arr << i ** 2 }
end
my_arr = [1, 2]
p square_array(my_arr) #=> [1, 4]
Using each with an Enumerator
def square_array(array)
Enumerator.new do |y|
array.each { |e| y << e ** 2 }
end
.take(array.length)
end
my_arr = [1, 2, 3, 4]
p square_array(my_arr) #=> [1, 4, 9, 16]
Here we create a new enumerator. We then write instructions for the enumerator telling it (when called upon) to yield values y according to the each block.
We then call all the yielded values for the given array by using take which returns an array with said values.
You need the index of the array element in order to set it to something else, so we will use each_with_index, and set the original array element to the new value:
irb(main):001:0> j = [2,3,4]
=> [2, 3, 4]
irb(main):002:0> j.each_with_index { |e, i| j[i] = e**2 }
=> [4, 9, 16]
irb(main):003:0>
If you can't use map, it seems natural to use reduce instead:
def square_array(array)
array.reduce([]) { |a, n| a << n * n }
end
But if that violates the spirit of the restriction, you could do it in a more manual way:
def square_array(array)
[].tap do |a|
array.each do { |n| a << n * n }
end
end
You can try this way using simple inject. For Doc refer: INJECT
> ar = [2,3,4,5]
=> [2, 3, 4, 5]
> ar.inject([]){|a,b| a << b**2}
=> [4, 9, 16, 25]
As has been pointed out in comments, map or collect is the natural way to do it in Ruby. However, if you just have to do without:
def square_array(ary)
a = Array.new(ary.length)
ary.each_index { |i| a[i] = ary[i] * ary[i] }
a
end

collect all elements and indices of an array in two separate arrays in Ruby

Suppose I have an array array = [1,2,3,4,5]
I want to collect all the elements and indices of the array in 2 separate arrays like
[[1,2,3,4,5], [0,1,2,3,4]]
How do I do this using a single Ruby collect statement?
I am trying to do it using this code
array.each_with_index.collect do |v,k|
# code
end
What should go in the code section to get the desired output?
Or even simpler:
[array, array.each_index.to_a]
I like the first answer that was posted a while ago. Don't know why the guy deleted it.
array.each_with_index.collect { |value, index| [value,index] }.transpose
Actually I am using an custom vector class on which I am calling the each_with_index method.
Here's one simple way:
array = [1,2,3,4,5]
indexes = *array.size.times
p [ array, indexes ]
# => [[1, 2, 3, 4, 5], [0, 1, 2, 3, 4]]
See it on repl.it: https://repl.it/FmWg

ruby check if any item in array exists in another array

Currently I have this code:
if !(allowed_params & password_protected_params).empty?
Which means "if anything in allowed_params is also in password_protected_params". This code works, but I find it a bit obfuscated and not friendly to the next developer that looks at this code.
Is there another, more readable way to check if anything in one array exists within another array?
EDIT
The block in question is this:
if !(allowed_params & password_protected_params).empty?
result = #user.update_with_password(allowed_params)
else
#only update trivial attributes
result = #user.update_without_password(allowed_params)
end
In the end I just added a variable to make it more readable (but still open to better suggestions):
needs_password = !(allowed_params & password_protected_params).empty?
if needs_password
result = #user.update_with_password(allowed_params)
else
#only update trivial attributes
result = #user.update_without_password(allowed_params)
end
There is not official synonym for Array#&. You can refactor your code into another method, and add a comment:
def intersects?(a, b)
!(a & b).empty?
end
# ...
if intersects? allowed_params, password_protected_params
# ...
Otherwise, you may want to extend the Array class, and define a method or add an alias_method to it:
class Array
alias_method :intersection, :&
def intersects?(array)
!(self.intersection(array)).empty?
end
end
[1, 2, 3].intersects? [3, 4, 5] # true
Bear in mind that changing core-classes is not a good-practice.
One ruby way could be
foo = [1, 2]
=> [1, 2]
bar = [1, 3]
=> [1, 3]
baz = [5, 3]
=> [5, 3]
bar.any?{|element| foo.include?(element)}
=> true
baz.any?{|element| foo.include?(element)}
=> false

arr.delete() vs arr.delete_at() in Ruby

I wrote the function below which accepts an array and returns a randomized version of it.
I've noticed that I sometimes end up with a nil element in randomizedArr when using list.delete(element) to remove an element from the array, but this does not happen when using list.delete_at(index) -- note that the latter is commented out in the below snippet. Am I missing something?
If there's a better way to do what I'm trying to achieve with this function then I would appreciate any suggestion. Thanks!
The array I'm passing to this function is a string array with ~2k elements. I'm passing in a clone of the original array so it doesn't become empty when the function is called. I'm using Ruby 2.1 on Windows 7.
def getRandomList(list)
randomizedArr = Array.new()
cnt = list.length
while (cnt >= 1) do
index = rand(cnt)
prod = list[index]
randomizedArr.push(prod)
list.delete(prod)
#list.delete_at(index)
cnt = cnt - 1
end
if randomizedArr.include?(nil)
puts "found nil element"
end
return randomizedArr
end #getRandomList()
I am not sure why you need to put all that logic when you can randomize the list by list.shuffle.
Refering to the Ruby documentation this is what I found to answer your question...
#To delete an element at a particular index:
arr = [2, 3, 4, 5] #I added this bit
arr.delete_at(2) #=> 4
arr #=> [2, 3, 5]
#To delete a particular element anywhere in an array, use delete:
arr = [1, 2, 2, 3]
arr.delete(2) #=> 2
arr #=> [1,3]
All of that can be found here https://ruby-doc.org/core-2.4.1/Array.html
arr.delete(2) will remove any instance of 2 in an array while delete_at(2) only removes the third value in the array.

How to calculate the sum of each position of subarrays?

Now my array is:
[[1,2,3],[4,5,6],[]]
I want to calculate this array and return a result as:
[5,7,9]
If there is a null array, remove it. Then plus every position for each sub array.
If use array's each method, maybe I can get the result. But is there a better way just use ruby's array method?
Another one liner
arr.reject(&:empty?).transpose.map{|x| x.reduce(:+)}
first get rid of the []
reject(&:empty?) # equivalent to reject{|x| x.empty?}
now .transpose to obtain
[[1, 4], [2, 5], [3, 6]]
Add up each sublist with
.map{|x| x.reduce(:+)}
Here's a one-liner that uses a lot of nice Ruby Array methods like reject, reduce, zip, and map.
array.reject(&:empty?).reduce { |result, e| result.zip(e).map { |x,y| x+y } }
See Ruby Array documentation for more details, and to see what other slick things you can do with them.
array = [[1,2,3],[4,5,6],[]]
require 'matrix'
Matrix[*array.reject { |a| a.empty? }].row_vectors.reduce(:+).to_a
#=> [5, 7, 9]

Resources