Using .map function to create hashes - ruby-on-rails

I have an array [5,2,6,4] and I would like to create a structure such as the first minus the second etc until the last row.
I have tried using map, but not sure how to proceed since i might need indxes.
I would like to store the result in something that looks like:
{1 => (5, 2, 3), 2 =>(2,6,-4), 3 => (6,4,2)}
So an array of x should return x-1 hashes.
Anybody knows how to do? should be a simple one.
Thank you.

First, you want to work with the array elements in pairs: 5,2, 2,6, ... That means you want to use each_cons:
a.each_cons(2) { |(e1, e2)| ... }
Then you'll want the index to get the 1, 2, ... hash keys; that suggests throwing a Enumerator#with_index into the mix:
a.each_cons(2).with_index { |(e1, e2), i| ... }
Then you can use with_object to get the final piece (the hash) into play:
a.each_cons(2).with_index.with_object({}) { |((e1, e2), i), h| h[i + 1] = [e1, e2, e1 - e2] }
If you think all the parentheses in the block's arguments are too noisy then you can do it in steps rather than a single one-liner.

You can use each_index:
a = [5, 2, 6, 4]
h = {}
a[0..-2].each_index { |i| h[i+1] = [a[i], a[i+1], a[i] - a[i+1]] }
h
=> {1=>[5, 2, 3], 2=>[2, 6, -4], 3=>[6, 4, 2]}

Try to use
each_with_index
Suppose you have an array:
arr = [3,[2,3],4,5]
And you want to covert with hash(key-value pair). 'Key' denotes an index of an array and 'value' denotes value of an array. Take a blank hash and iterate with each_with_index and pushed into the hash and finally print the hash.
Try this:
hash={}
arr.each_with_index do |val, index|
hash[index]=val
end
p hash
Its output will be:
{0=>3, 1=>[2, 3], 2=>4, 3=>5}
If you want that index always starts with 1 or 2 etc then use
arr.each.with_index(1) do |val, index|
hash[index] = val
end
Output will be:
{1=>3, 2=>[2, 3], 3=>4, 4=>5}

Related

Remove array elements at indices non destructively

Let's say you have something like this:
my_array = ['some_rather', 'long_named', 'array_element', 'entry']
I want to remove arbitrary entries by index from my_array without changing it and I want the filtered (i.e. array with indices removed) to be returned from my call. Furthermore, I want to avoid chaining 4 separate calls and write a block doing so.
Example:
filtered_array = my_array.drop_indices(1,3)
You could chain Enumerable's with_index onto Array's reject method to do what you want, though this might violate your desire to not chain separate method calls or write a block to do this:
my_array = ['some_rather', 'long_named', 'array_element', 'entry', 'long_named']
indices_to_remove = [1, 3]
filtered = my_array.reject.with_index { |_, index| indices_to_remove.include?(index) }
p filtered # => ["some_rather", "array_element", "long_named"]
p my_array # => ["some_rather", "long_named", "array_element", "entry", "long_named"]
If this isn't acceptable, the only other thing I can think of right now, to keep duplicate items (as noted in my comment to your solution), is to change from indices_to_remove to indices_to_keep:
my_array = ['some_rather', 'long_named', 'array_element', 'entry', 'long_named']
indices_to_remove = [1, 3]
indices_to_keep = [*(0...my_array.length)] - indices_to_remove
filtered = my_array.values_at(*indices_to_keep)
p filtered # => ["some_rather", "array_element", "long_named"]
p my_array # => ["some_rather", "long_named", "array_element", "entry", "long_named"]
For Arrays with duplicate Elements the best I know is:
array = [0,15,8,15,8]
indices_to_remove = [1,4]
res = array.reject.with_index{ |_,i| indices_to_remove.include?(i) }
returns
[0,8,15]
Additionally for arrays with unique entries such as a set of users
(using variable definitions from the question)
filtered_array = my_array - my_array.values_at(1,3)
Bonus, if your indices are inside an array themselves:
indices_to_remove = [1,3]
filtered_array = my_array - my_array.values_at(*indices_to_remove)
I think this is rather descriptive, not awkward and not shorter than needed.
One more possible solution with some addition, now it's also will work with negative indexes:
array = %w( a b c d e f )
indexes = [1, 2, -1, -9, -6, 6]
def array_except(array, *indexes)
indexes = indexes.map { |e| e.negative? ? e + array.length : e }
array.values_at(*((0...array.length).to_a - indexes))
end
array_except(array, *indexes)
=> ["d", "e"]
array_except(array, 0, -1)
=> ["b", "c", "d", "e"]

Rails remove subarray from array

In my Rails 5 app I have something like this:
a = [1,2,3]
a.map do |entry|
entry.delete if condition == true
end
This removes the entry if the condition is true.
Now I have this:
a = [[1,2],[2,3],[3,4]]
a.map do |entry|
entry.delete if condition == true
end
This loops through a but now entry is an array and delete should remove the entire entry but instead I get:
wrong number of arguments (given 0, expected 1)
Dos anybody know how I can loop through an array of arrays and remove an entire subarray?
Try this:
a.delete_if {condition}
For example:
a = [[1,2],[2,3],[3,4]]
a.delete_if {|entry| entry[0] == 1 }
# returns [[2, 3], [3, 4]]
instead of using map you should use flat_map see: https://apidock.com/ruby/Enumerable/flat_map

Ruby:-- Accept array as input and put it into hash

User must enter the array as input. Hash has to accept the input array elements as values.
Create a Ruby program for this by using loops. If array completed print this statement “All array elements are assigned to keys in the hash”
A = [1, 6, 4, 5]
H = {“k1” => 1
“k2” => 6
“k3” => 4
“k4” => 5}
Another solution can be,
a.each_with_index.inject({}) { |m,(a,i)| m["k#{i+1}"] = a; m }
Update: answering to your question
puts 'Enter number of hash elements'
n = gets.to_i
n.times |i|
hash["k#{i+1}"] = gets.to_i
end
puts 'All array elements are assigned to keys in the hash'
A = [1, 6, 4, 5]
Hash[[*'k1'.."k#{A.length}"].zip(A)]

Convert array to single object if array is a single object

Really simple question.
Is there a method to do the following?
["a"] => "a"
[1] => 1
[1,"a"] => [1, "a"]
i.e. if an array is a single object, return the object, otherwise return the array.
Without doing something ugly like
array.length == 1 ? array[0] : array
basically you should stick to what you wrote - it's simple and does what it should.
of course you may always monkey patch the Array definition... (unrecommended, but it does what you expect)
class Array
def first_or_array
length > 1 ? self : self[0]
end
end
[1].first_or_array # 1
[1, 2].first_or_array # [1, 2]

How do you double number in ruby for an iterator

Need to double each value in my array. I know double is not a command, but not sure what else to use.
odds = [1,3,5,7,9]
array.each do |x|
x += double
print "#{x}"
end
Use Array#map to create a new array
odds = [1,3,5,7,9]
arr = odds.map{|x| x*2}
arr.inspect
# => [2,6,10,14,18]
To modify the same array use Array#map!
odds = [1,3,5,7,9]
odds.map!{|x| x*2}
odds.inspect
# => [2,6,10,14,18]
Do you mean 'double' as in multiply by 2, or double as in duplicate?
array = [1,3,5,7,9]
array.each { |x| print "#{x*2}"; }
But you probably want either a new array, or to map your existing array,
result = []
result = array.map { |x| x*2 }
#or
result = array.map! { |x| x*2 }
Here is an example of duplicate,
result = []
array.map { |x| result << x; result << x; } #duplicate
see here: http://www.natontesting.com/2011/01/01/rubys-each-select-and-reject-methods/
Doing the Simplest Thing Possible
The simplest thing to do is to simply iterate over your array with Array#map and Kernel#p. For example:
odds = [1, 3, 5, 7, 9]
odds.map { |i| p i*2 }
Defining a Custom Method
If you need more control, you can create a custom method that handles a block or returns an enumerator. For example:
def double *array
array.flatten!
block_given? ? array.map { |i| yield i*2 } : array.map { |i| i*2 }.to_enum
end
enumerator = double 1, 2, 3
#=> #<Enumerator: ...>
enumerator.each { |i| p i }
#=> [2, 4, 6]
double(1, 2, 3) { |i| p i }
#=> [2, 4, 6]
This is probably overkill for your use case, but it's a useful technique to know if you want to work with enumerators and blocks. Hope it helps!
The way that I have found to do it is to times / equal it by 2. For example:
odds = [1,3,5,7,9]
odds.each do |x|
x *= 2
print x
end

Resources