I'm doing http://www.rubeque.com/problems/queue-continuum/solutions/51a26923ba804b00020000df and I spent a while there. I can't realize why this code doesn't pass
def initialize(queue)
#q = queue
end
def pop(n=1)
#q.shift(n)
end
def push(arr)
arr.each { |x|
#q.push(x)
}
return true
end
def to_a
#q
end
but this works perfectly.
def initialize(queue)
#q = queue
end
def pop(*n)
#q.shift(*n)
end
def push(arr)
#q.push(*arr)
return true
end
def to_a
#q
end
i'm totally confused about
def pop(*n)
#q.shift(*n)
end
and
def push(arr)
#q.push(*arr)
end
why should I take (arr) as array and than change it into... *arr which is Array of array? I'm confused, please help!
The splat works in two ways.
When receiving arguments, it combines arguments into an array.
def foo *args; args end
foo(1) # => [1]
foo(1, 2, 3) # => [1, 2, 3]
When giving arguments, it decomposes an array into arguments.
def bar x, y, z; y end
bar(*[1, 2, 3]) # => 2
def baz x; x end
baz(1) # => [1]
baz(1, 2, 3) # => Error
The *arr you are wondering is the latter case. It is not an object like [1, 2, 3] (hence, not an array of arrays). It is a part of arguments (like 1, 2, 3) passed to a method.
There are other uses of splats (as in array literals, case statements, etc.), but their function is either of the two uses above.
Related
I have:
class Thing
def initialize
#array = [[0, 0, 0], [1, 1, 1]]
end
end
thing = Thing.new
The normal way to access an element in #array is to use [] as in:
#array[0][1] # => 0
I am trying to overwrite [] so as to get results like this:
position_array = [0, 1]
#array[position_array] # => 0
This is my attempt:
class Thing
def [](position_array)
index_row, index_col = position_array
#array[index_row][index_col]
end
def get_value(position_array)
#array[position_array] # doesn't work
# self[position_array] # does work
end
end
thing.get_value([0, 1])
# >> 'get_value': no implicit conversion of Array into Integer (TypeError)
Why do I need to index the Thing object in order to index #array?
Just think of message and receiver.
#array[position_array] sends the message [] to the receiver #array. #array is an instance of Array, so the method Array#[] gets invoked.
self[position_array] sends the message [] to the receiver self. Within instance methods, self refers to that instance. And because self is an instance of Thing, the method Thing#[] gets invoked.
Since Thing is a subclass of Object and not a subclass of Array (nothing wrong here, you shouldn't subclass Array anyway), your implementation of [] does not override Array#[]. Both methods are totally independent of each other, just like String#[] or Hash#[].
This is how I would approach it:
class Thing
def initialize
#array = [[1, 2, 3], [4, 5, 6]]
end
def [](i, j)
#array[i][j]
end
end
thing = Thing.new
thing[0, 1] #=> 2
thing[1, 1] #=> 5
You could use a prepended method to non-invasively override the [] method in Array by duck-typing the parameter passed to the [] method, and then calling the original if its not what you expect. Then you don't need a Thing object at all.
module MyArrayExtension
def [] (*param)
if param.size == 2
row, col = param
raise ArgumentError, 'Row must be an integer' if row.class != Integer
raise ArgumentError, 'Column must be an integer' if col.class != Integer
raise ArgumentError, "Element at row #{row} is not an array" if self[row].class != Array
self[row][col]
else
super
end
end
end
class Array
prepend MyArrayExtension
end
thing = [[1,2,3],[4,5,6]]
puts "The 2D array is: #{thing}"
puts "Extension used on the thing to get at element 1 of first array:"
puts thing[0,1]
puts '-' * 20
normal = [1,2,:blah,4,5]
puts "Normal array is #{normal}"
puts "Original [] method used to get the 3rd element:"
puts normal[2]
puts '-' * 20
puts "Using the extension on the non-2D array:"
puts normal[0,1]
The output of this program is:
The 2D array is: [[1, 2, 3], [4, 5, 6]]
Extension used on the thing to get at element 1 of first array:
2
--------------------
Normal array is [1, 2, :blah, 4, 5]
Original [] method used to get the 3rd element:
blah
--------------------
Using the extension on the non-2D array:
./test.rb:9:in `[]': Element at row 0 is not an array (ArgumentError)
from ./test.rb:35:in `<main>'
When using array.each you can specify the function in two forms:
Curly Braces:
a = [1,2,3]
a.each { |x| puts x * x }
Output:
1
4
9
=> [1, 2, 3]
'do' Syntax:
a = [1,2,3]
a.each do |x|
puts (x * x)
end
Output:
1
4
9
=> [1, 2, 3]
Question:
How can I replicate the 'do' syntax style with my own custom function? The closest to the curly brace style I can get is:
What I've tried:
def PutWith2Arg(proc)
puts proc.call(2)
end
PutWith2Arg(Proc.new { |x| x + 100 })
Output:
102
=> nil
The do |foo| … end and { |foo| … } syntaxes are equivalent. These are 'blocks' in Ruby, and any method can get them. To call them you need to either:
def my_method # No need to declare that the method will get a block
yield(42) if block_given? # Pass 42 to the block, if supplied
end
my_method do |n|
puts "#{n} times 2 equals #{n*2}"
end
#=> "42 times 2 equals 84"
my_method{ |n| puts "#{n} times 2 equals #{n*2}" }
#=> "42 times 2 equals 84"
my_method # does nothing because no block was passed
or, for more sophisticated uses:
def my_method( &blk ) # convert the passed block to a Proc named blk
blk.call( 42 ) if blk
end
# Same results when you call my_method, with or without a block
The latter style is useful when you need to pass the block on to another method. If you have a Proc or Lambda referenced by a variable, you can pass it to a method as the block for that method using the & syntax:
def my_method( &blk ) # convert the passed block to a Proc named blk
[1,2,3].each( &blk ) # invoke 'each' using the same block passed to me
end
my_method{ |x| p x=>x**2 }
#=> {1=>1}
#=> {2=>4}
#=> {3=>9}
For more details, this webpage is fairly instructive.
How do I return Enumerator from my array wrapper without using already existing array iterators?
class MyArray
def initialize
#inner = []
end
def each
index = 0
while index < #inner.size
yield #inner[index] if block_given?
index += 1
end
end
end
I can't figure out how to avoid calling things like #inner.each at the end of the each method.
Given:
#inner = [1, 2, 3]
Code
#inner.to_enum
will return an enumerator.
enum = #inner.to_enum
enum.each{|e| p e}
# => 1, 2, 3
I want to pass a block to a function, and then call that block with some additional parameters as follows:
def foo(&block)
some_array = (1..3).to_a
x = 7 # Simplified
result = some_array.map &block # Need some way to pass in 'x' here
end
def a_usage_that_works
foo do |value|
value
end
end
def a_usage_that_doesnt_work
foo do |value, x|
x # How do I pass in x?
end
end
# rspec to demonstrate problem / required result
describe "spike" do
it "works" do
a_usage_that_works.should == [1,2,3]
end
it "doesn't work" do
a_usage_that_doesnt_work.should == [7, 7, 7]
end
end
How can I pass in the additional parameter to the block?
Create another block and call first one from it.
def foo(&block)
some_array = (1..3).to_a
x = 7 # Simplified
result = some_array.map {|elem| block.call(elem, x)}
end
You pass to the block by yielding to it.
def foo(&block)
some_array = [1,2,3]
x = 7
some_array.map{|el| yield el, x}
end
p foo{|p1, p2| p2} #=>[7,7,7]
p foo{|p1, p2| p1} #=>[1,2,3]
You can use a higher-order function to generate a simplified function:
Let's assume that the block we pass to foo will accept value, x.
Naive strategy, using an inline-defined x:
def foo(&block)
some_array = (1..3).to_a
x = 7
simple_func = proc {|value| block.call(value, x) }
result = some_array.map &simple_func
end
Strategy using separation of concerns:
def get_simple_func(block)
# This assumes x won't change per iteration.
# If it can change, you can move the calculation inside the proc.
# Moving it inside also allows the calculation to depend on "value", in case you want that.
x = complex_calculation_for_x()
proc {|value| block.call(value, x) }
end
def foo(&block)
some_array = (1..3).to_a
simple_func = get_simple_func(block)
result = some_array.map &simple_func
end
Obviously you shouldn't use this when x is a literal value because it would be over-engineering. But as the calculation of x becomes more complex, separating it out makes the code more readable. Also, foo can focus on the specific task of applying the function to some_array.
How do I call a method, given its name, on an element of an array?
For example, I could have:
thing = "each"
I want to be able to do something like:
def do_thing(thing)
array = [object1,object2]
array[0].thing
end
so that do_thing(to_s), for example, would run object1.to_s.
You can use public_send or send. public_send only sends to public methods while send can see public and private methods.
def do_thing(thing)
array = [1,2,3]
array.public_send(thing)
end
do_thing('first')
# => 1
do_thing(:last)
# => 3
Update A more general version:
def do_thing(array, index, method, *args)
array[index].public_send(method, *args)
end
do_thing([1, 2, 3], 0, :to_s)
# => "1"
do_thing([[1,2], [3, 4]], 0, :fetch, 0)
# => 1
require 'ostruct'
o = OpenStruct.new(attribute: 'foo')
do_thing([o], 0, :attribute=, 'bar')
o.attribute == 'bar'
# => true
Object#send
thing = "each"
def do_thing(thing)
array = [1,2,3]
array.send(thing)
end
From the doc:
class Klass
def hello(*args)
"Hello " + args.join(' ')
end
end
k = Klass.new
k.send :hello, "gentle", "readers" #=> "Hello gentle readers"
Here is an example to help you out although I don't have any idea what objects are residing inside your array:
arr = [Array.new(2,10),"abc" ]
arr.each{|i| p i.send(:length)}
#>>2
#>>3