Related
I have been reading this:
https://docs.ruby-lang.org/en/2.4.0/Enumerator.html
I am trying to understand why someone would use .to_enum, I mean how is that different than just an array? I see :scan was passed into it, but what other arguments can you pass into it?
Why not just use .scan in the case below? Any advice on how to understand .to_enum better?
"Hello, world!".scan(/\w+/) #=> ["Hello", "world"]
"Hello, world!".to_enum(:scan, /\w+/).to_a #=> ["Hello", "world"]
"Hello, world!".to_enum(:scan).each(/\w+/).to_a #=> ["Hello", "world"]
Arrays are, necessarily, constructs that are in memory. An array with a a lot of entries takes up a lot of memory.
To put this in context, here's an example, finding all the "palindromic" numbers between 1 and 1,000,000:
# Create a large array of the numbers to search through
numbers = (1..1000000).to_a
# Filter to find palindromes
numbers.select do |i|
is = i.to_s
is == is.reverse
end
Even though there's only 1998 such numbers, the entire array of a million needs to be created, then sifted through, then kept around until garbage collected.
An enumerator doesn't necessarily take up any memory at all, not in a consequential way. This is way more efficient:
# Uses an enumerator instead
numbers = (1..1000000).to_enum
# Filtering code looks identical, but behaves differently
numbers.select do |i|
is = i.to_s
is == is.reverse
end
You can even take this a step further by making a custom Enumerator:
palindromes = Enumerator.new do |y|
1000000.times do |i|
is = (i + 1).to_s
y << i if (is == is.reverse)
end
end
This one doesn't even bother with filtering, it just emits only palindromic numbers.
Enumerators can also do other things like be infinite in length, whereas arrays are necessarily finite. An infinite enumerator can be useful when you want to filter and take the first N matching entries, like in this case:
# Open-ended range, new in Ruby 2.6. Don't call .to_a on this!
numbers = (1..).to_enum
numbers.lazy.select do |i|
is = i.to_s
is == is.reverse
end.take(1000).to_a
Using .lazy here means it does the select, then filters through take with each entry until the take method is happy. If you remove the lazy it will try and evaluate each stage of this to completion, which on an infinite enumerator never happens.
I'm trying to get the banner image on my website to change once a day. I can see ruby has srand which will let me input a number for the date and return the same result every time it is called on the same day but this returns a very long number. I also saw rand lets me use a range like rand(a..b).
Is there any way I can use srand with a range like I can with rand?
You can create a special/designated random number generator with any seed value you like:
special = Random.new 42 # create a new instance of Random seeded with 42
20.times { p special.rand(5..10) } # generate 20 random ints in range 5 to 10
Your special instance of Random is independent of kernel#rand unless you use srand to initialize it with the same seed value.
You could use the date's Julian day number as the seed:
require 'date'
Date.new(2017, 6, 1).jd #=> 2457906
Date.new(2017, 6, 2).jd #=> 2457907
Date.new(2017, 6, 3).jd #=> 2457908
This can then be used to generate a random daily index:
def number_of_banners
10
end
def daily_banner_index(date = Date.today)
Random.new(date.jd).rand(number_of_banners)
end
daily_banner_index
#=> 8
Or a random daily element from an array:
def banners
%w(foo_banner bar_banner baz_banner)
end
def daily_banner(date = Date.today)
banners.sample(random: Random.new(date.jd))
end
daily_banner
#=> "bar_banner"
To avoid breaking the random number generator for the rest of my application I went with
(Date.today.to_s.gsub('-','').to_i) % number_of_banners
While not exactly random it should work well enough for this case but I would be interested in better solutions.
How does Array#sample work, if you pass a range as random numbers generator?
As here :
> [*1..10].sample(random: 1..3)
=>9
As per the doc, sample(random: rng), rng is not a Range Object, as you might thought. rng is a Random number generator.
The optional rng argument will be used as the random number generator.
a = (1..10).to_a
r = Random.new
r2 = r.dup
a1 = a.sample(random: r)
a2 = a.sample(random: r2)
a1 == a2 # => true
The point is #sample, takes its second argument as keyword argument. If we use something like foo: 12 or rng: (1..2), it will give ArgumentError: unknown keyword:. The optional argument will be acceptable only when you will supply it a value as random: <any random number generator>. Now, coming to your point :
r = 1..3
a1 = [*1..10].sample(random: r)
a2 = [*1..10].sample(random: r)
a1 == a2 # => false
When you are passing the second argument as random: r, r must be Random object, or an object that responds to #rand. Remember with the second argument, you are telling #sample, to use your random number generator instead of the default one it uses in absence of the optional argument.
Here is one custom implementation of a RNG :
ob = Object.new
def ob.to_int
5000
end
gen_to_int = proc do |max|
ob
end
class << gen_to_int
alias rand call
end
ary = (0...10000).to_a
ary.sample(random: gen_to_int) # => 5000
ary.sample(random: gen_to_int) # => 5000
ary.sample(random: gen_to_int) # => 5000
This will give you the understanding about #sample with the optional argument. Look for more examples from #test_sample_random.
Update
How does Array#sample work, if you pass a range as random numbers generator?
To answer this, I would take a help of the TracePoint class.
trace = TracePoint.new(:c_call) do |tp|
p [tp.lineno, tp.defined_class, tp.method_id, tp.event]
end
trace.enable do
[1,2,3,4,5,66,4].sample(random: 1..3)
end
# >> [6, Array, :sample, :c_call]
# >> [6, Kernel, :rand, :c_call]
# >> [6, Kernel, :respond_to_missing?, :c_call]
So, from the above call stack, you can see - Array#sample method has been called. Now internally, Ruby called Kernel#rand on the Range object. Now, (1..3).respond_to? returned false(because #rand - it is a_private_ instance method for Range), that's why finally #respond_to_missing? method has been called to do the job.
I have this code below:
a = [435,276,434]
def product(a)
final = 1
for e in a
for p in a[e]
final*=p
end
end
final
end
puts product(a)
I'm wondering how I can iterate over this array twice where the result is 4*3*5 = 60, 2*7*6 = 85, and 4*3*4 = 48
I wrote some code up above which I thought would do the trick here but Ruby keeps on returning an error.
A few points to consider:
In Ruby you basically never use a for loop to iterate over things. #each is better. You get to pass a block to that, which gives you all kinds of room for flexibility and expressiveness.
Also, you can't - normally - iterate over an Integer. Remember that an Integer is a store of numerical value, not a particular representation, so it would have to be dependent on the base of the representation you wanted. If you want a string of characters, each of which happen to be numbers, well, guess what? You want a String, like seph's solution here. Or an Array, which would probably make even more sense because each integer would remain an integer and wouldn't have to be parsed back and forth.
Tell you what, let's build a really cool method to do this and staple this on to Integer, and hopefully demonstrate some of Ruby's cool features.
class Integer
include Enumerable
def each(base = 10, &blk)
front, back = abs.divmod(base)
if front > 0
front.each(base, &blk)
end
yield back
end
end
This little number takes a base and a block, gets the absolute value of the integer (since technically the minus isn't a digit), then uses divmod to split the number, chopping off the final digit. We store the pieces in front and back. We check to see if there are any more digits, indicated by front being 0, and if there is we recursively call this method, with that block. Then we just yield the back, sending the digit to the block.
Since we have now defined an each method, we are now free to include Enumerable which gets us a ton of stuff!
As long as that modification is active, your product method becomes:
(if you wanted to print 60 84 48): a.map {|n| n.reduce(:*)}
(or if you wanted to print 241920): a.reduce(:*).reduce(:*)
Pretty nice!
So, this total solution is quite a bit longer than seph's one-liner, and in truth if I needed to actually do something I would just to_s. Is my solution quicker to execute? Who knows? It's certainly more expressive, though, and that's why you're using Ruby in the first place.
If you want to solve a problem, yeah, absolutely, to_s. But if you want your code to express a philosophy you have about numbers, about how really they're just collections too - and they are, in a weird set theory kind of way, Ruby lets you empower them to be that. And this way that doesn't need Strings at all, they're totally free of their grudging assistance. And you can iterate through different bases, which is super useful if you're doing hex or binary, which preserves more of the numbery essence of them.
In this world that you and I have built together, Jamaal, little integers run wild through the forests with the big boys. And that's wonderful.
You could convert it to a string(.to_s). Then it's easy to get each digit as a char(.chars), convert them back to an integers(.map(&:to_i)) and multiply them together(.reduce(:*))
a = [435,276,434]
a.map {|n| n.to_s.chars.map(&:to_i).reduce(:*) }
=> [60, 84, 48]
Here's one way you could fix your code:
a = [435,276,434]
def product(a)
result = [] # Create an empty array that will become [60, 85, 48]
for e in a
final = 1
# Convert the integer e to a string (e.g., "435")
str = e.to_s
# Iterate over each char of the string (e.g., "4", "3" and "5")
str.each_char do |c|
# Convert the character 'c' to an integer (digit) then multiply final by that integer
final *= c.to_i
end
# Append the value of final to the result array
result << final # e.g., when result = [60], result << 85 => [60, 85]
end
result # => [60, 85, 48]
end
product(a) # => [60, 85, 48]
Now let's see how we can improve it. Firstly, we can chain operations and avoid the use of the temporary variable str. Also, you'll find that for loops, each is generally preferable to for (especially because you can use a block with each), so I'll change that too. While I'm at it, since the each_char loop contains only one statement, I'll write the block with brackets rather than do/end. We now have:
def product(a)
result = [] # Create an empty array that will become [60, 85, 48]
a.each do |e|
final = 1
e.to_s.each_char {|c| final *= c.to_i}
result << final
end
result
end
When I look at this, I'm thinking I want to convert each element of the array a to something else (the product of its digits). That suggests the use of the Array method map! (or its synonym, collect!), rather than each. Since a is the argument of the method product, if I use a.map!, that will change the values of a in the method that calls product. That may or may not be OK, but since I'm returning an array of the computed values, it's probably not OK, so I'll apply map! to a copy of a. (It's called a "shallow" copy, which is not important here, but can be in other situations.) We now have this:
def product(a)
result = a.dup
result.map! do |e|
final = 1
e.to_s.each_char {|c| final *= c.to_i}
final
end
result
end
We don't need the last result, because map! returns result (as well as changing result). Hey, that also means we can use just map (makes no difference). Also, we can chain a.dup and map to get rid of result:
def product(a)
a.dup.map do |e|
final = 1
e.to_s.each_char {|c| final *= c.to_i}
final
end
end
Man, we're cookin' with gas! Next, whenever you see a block that computes the product or sum of something, think inject (or its synomym, reduce):
def product(a)
a.dup.map do |e|
e.to_s.each_char.inject(1) {|final, c| final * c.to_i}
end
end
Suppose a < 0. What to do? (#Leon's answer twigged me to that possibility.) A negative receiver makes no sense to each, so let's raise an exception if that happens:
def product(a)
raise RuntimeError, "Receiver must be non-negative" if self < 0
a.dup.map do |e|
e.to_s.each_char.inject(1) {|final, c| final * c.to_i}
end
end
You may want to stop here, but you could replace map with another `inject:
def product(a)
raise RuntimeError, "Receiver must be non-negative" if self < 0
a.inject([]) {|result, e| result.concat.e.to_s.each_char.inject(1) {|final, c| final * c.to_i}}
end
Here the argument for inject is an empty array called result. Notice that, since we haven't changed a, we no longer needed dup. (I see #Kingston arrived at a similar answer.) If you prefer, you could write this as:
def product(a)
raise RuntimeError, "Receiver must be non-negative" if self < 0
a.inject([]) {|result, e| result << e.to_s.each_char.inject(1) {|final, c| final * c.to_i}; result}
end
but notice the need for that pesky ; result an the end.
You might think that the end result of all these "improvements" is too much of a mind-bender, or that the author is just showing off. That's what I thought when I was new to Ruby. With experience, however, you will find it is very natural and reads like a sentence. It also makes debugging easier: working left-to-right, you can test each link of the chain to make sure it's working.
a.collect{|x|
result = 1
x.to_s.split('').each{|y| result *= y.to_i}
result
}
If the intent is to just iterate over the digits, you can use the string slice methods too.
num = a[0].to_s # "435"
final = num[0,1].to_i * num[1,1].to_i * num[2,1].to_i #4*3*5
or
final = num[0..1].to_i * num[1..2].to_i * num[2..3].to_i
For the given question, if you know it is an array of 3 digits each, then you can skip the inner loop and the solution could be like this:
a = [435,276,434]
def product(a)
a.map! do |digits|
final = 1
num = digits.to_s
final = num[0,1].to_i * num[1,1].to_i * num[2,1].to_i
end
end
puts product(a).inspect
This answer is just for the said question. Since it manipulates the same array, it edits the receiver. For a more detailed and complete solution, check out Cary Swoveland's answer.
How can I get a lazy array in Ruby?
In Haskell, I can talk about [1..], which is an infinite list, lazily generated as needed. I can also do things like iterate (+2) 0, which applies whatever function I give it to generate a lazy list. In this case, it would give me all even numbers.
I'm sure I can do such things in Ruby, but can't seem to work out how.
With Ruby 1.9 you can use the Enumerator class. This is an example from the docs:
fib = Enumerator.new { |y|
a = b = 1
loop {
y << a
a, b = b, a + b
}
}
p fib.take(10) #=> [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
Also, this is a nice trick:
Infinity = 1.0/0
range = 5..Infinity
p range.take(10) #=> [5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
This one only works for consecutive values though.
Recently Enumerable::Lazy has been added to ruby trunk. We'll see it in ruby 2.0.
In particular:
a = data.lazy.map(&:split).map(&:reverse)
will not be evaluated immediately.
The result is instance of Enumerable::Lazy, that can be lazy chained any further. If you want to get an actual result - use #to_a, #take(n) (#take is now lazy too, use #to_a or #force), etc.
If you want more on this topic and my C patch - see my blog post Ruby 2.0 Enumerable::Lazy
Lazy range (natural numbers):
Inf = 1.0/0.0
(1..Inf).take(3) #=> [1, 2, 3]
Lazy range (even numbers):
(0..Inf).step(2).take(5) #=> [0, 2, 4, 6, 8]
Note, you can also extend Enumerable with some methods to make working with lazy ranges (and so on) more convenient:
module Enumerable
def lazy_select
Enumerator.new do |yielder|
each do |obj|
yielder.yield(obj) if yield(obj)
end
end
end
end
# first 4 even numbers
(1..Inf).lazy_select { |v| v.even? }.take(4)
output:
[2, 4, 6, 8]
More info here:
http://banisterfiend.wordpress.com/2009/10/02/wtf-infinite-ranges-in-ruby/
There are also implementations of lazy_map, and lazy_select for the Enumeratorclass that can be found here:
http://www.michaelharrison.ws/weblog/?p=163
In Ruby 2.0.0, they were introduced new method "Lazy" in Enumerable class.
You can check the lazy function core and usage here..
http://www.ruby-doc.org/core-2.0/Enumerator/Lazy.html
https://github.com/yhara/enumerable-lazy
http://shugomaeda.blogspot.in/2012/03/enumerablelazy-and-its-benefits.html
As I already said in my comments, implementing such a thing as lazy arrays wouldn't be sensible.
Using Enumerable instead can work nicely in some situations, but differs from lazy lists in some points: methods like map and filter won't be evaluated lazily (so they won't work on infinite enumerables) and elements that have been calculated once aren't stored, so if you access an element twice, it's calculated twice.
If you want the exact behavior of haskell's lazy lists in ruby, there's a lazylist gem which implements lazy lists.
This will loop to infinity:
0.step{|i| puts i}
This will loop to infinity twice as fast:
0.step(nil, 2){|i| puts i}
This will go to infinity, only if you want it to (results in an Enumerator).
table_of_3 = 0.step(nil, 3)
I surprised no one answered this question appropriately yet
So, recently I found this method Enumerator.produce which in conjunction with .lazy does exactly what you described but in ruby-ish fashion
Examples
Enumerator.produce(0) do
_1 + 2
end.lazy
.map(&:to_r)
.take(1_000)
.inject(&:+)
# => (999000/1)
def fact(n)
= Enumerator.produce(1) do
_1 + 1
end.lazy
.take(n)
.inject(&:*)
fact 6 # => 720
The right answer has already identified the "lazy" method, but the example provided was not too useful. I will give a better example of when it is appropriate to use lazy with arrays. As stated, lazy is defined as an instance method of the module Enumerable, and it works on EITHER objects that implement Enumerable module (e.g. arrays - [].lazy) or enumerators which are the return value of iterators in the enumerable module (e.g. each_slice - [].each_slice(2).lazy). Note that in Enumerable module, some of the instance methods return more primitive values like true or false, some return collections like arrays and some return enumerators. Some return enumerators if a block is not given.
But for our example, the IO class also has an iterator each_line, which returns an enumerator and thus can be used with "lazy". The beautiful thing about returning an enumerator is that it does not actually load the collection (e.g. large array) in memory that it is working on. Rather, it has a pointer to the collection and then stories the algorithm (e.g. each_slice(2)) that it will use on that collection, when you want to process the collection with something like to_a, for example.
So if you are working with an enumerator for a huge performance boost, now you can attach lazy to the enumerator. So instead of iterating through an entire collection to match this condition:
file.each_line.select { |line| line.size == 5 }.first(5)
You can invoke lazy:
file.each_line.lazy.select { |line| line.size == 5 }.first(5)
If we're scanning a large text file for the first 5 matches, then once we find the 5 matches, there is no need to proceed the execution. Hence, the power of lazy with any type of enumerable object.
Ruby Arrays dynamically expand as needed. You can apply blocks to them to return things like even numbers.
array = []
array.size # => 0
array[0] # => nil
array[9999] # => nil
array << 1
array.size # => 1
array << 2 << 3 << 4
array.size # => 4
array = (0..9).to_a
array.select do |e|
e % 2 == 0
end
# => [0,2,4,6,8]
Does this help?