Getting random element from ruby array (your solution)? - ruby

what is your version to this problem ?
i'm doing so:
array = [1,2,3,4,5,6,7,8,9]
puts array.sort_by { array }.first
puts array[rand(array.size)]
puts array.shuffle.first
puts array.sample

I use array.sample. It is MUCH easier to read than the first 2 and slightly easier to read than the third.

Related

Ruby: Understanding .to_enum better

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.

Program to take input from command line into an array and find the biggest among them

I am new to Ruby and just can't figure out how you take input for an array from a user and display it.If anyone could clear that I can add my logic to find the biggest number.
#!/usr/bin/ruby
puts "Enter the size of the array"
n = gets.chomp.to_i
puts "enter the array elements"
variable1=Array.new(n)
for i in (0..n)
variable1[i]=gets.chomp.to_i
end
for i in (0..n)
puts variable1
end
How about capturing the array in one line?
#!/usr/bin/ruby
puts "Enter a list of numbers"
list = gets # Input something like "1 2 3 4" or "3, 5, 6, 1"
max = list.split.map(&:to_i).max
puts "The largest number is: #{max}"
You are doing it ok. But try this little change
#!/usr/bin/ruby
puts "Enter the size of the array"
n = (gets.chomp.to_i - 1)
puts "enter the array elements"
variable1=Array.new(n)
for i in (0..n)
variable1[i]=gets.chomp.to_i
end
puts variable1
or for undefined number of values here is one way
#!/usr/bin/ruby
puts "enter the array elements (type 'done' to get out)"
input = gets.chomp
arr = []
while input != 'done'
arr << input.to_i
input = gets.chomp
end
puts arr
I believe that this is a little bit more elegant solution.
puts "Please enter numbers separated by spaces:"
s = gets
a = s.split(" ")
#Displays array
puts a
#Displays max element
puts a.max
First you collect the series of numbers from the user, then you use a split method on the string, which converts it to the array. If you want to use some other separator, like "," than you can write s.split(","). After that you can use your logic to find the biggest number or you could just use max method.
Some feedback:
chomp.to_i is a bit redundant, since the latter will also remove newlines.
for x in y is not commonly seen in idiomatic Ruby code. It basically behaves like each with slightly different scoping rules and probably should have been removed from the language a while ago.
Ruby arrays are dynamic, so no need to preinitialize them. Something like (1..n).map { gets.to_i } would also produce the array you need.
Displaying it can then be done like this: array.each { |n| puts n }
Alternatively you can use the strip approach outlined before, take the numbers as command line arguments in ARGV or pipe into your program using ARGF.

ruby - lazily iterate through an array

I want to iterate through a part of an array. For example, I try to print every element except the first one:
array[1..-1].each {|e| puts e}
But array[1..-1] builds a new Array. It's wasteful if array is very huge. Another straightforward approach:
(1...array.size).each { |i| puts array[i] }
It works. But I wonder if there are some more elegant tricks.
Ruby 2.0 will ship Lazy enumerables (fantastic news!), for now we can warm up the engines using gems like enumerable-lazy:
require 'enumerable/lazy'
xs.lazy.drop(1).each { |x| puts x }
That's not bad, but conceptually it doesn't exactly apply to your case, since you already have an array, not a lazy object (a linked list) that you must traverse to discard elements (ok, we are just discarding one element here, it wouldn't be a deal-breaker). So you could just abstract your solution (that one using a range) as Enumerable#each_from(start_index) if you plan to use it a lot.
More: you could also create an extension to enumerable-lazy Array#lazy_slice(range), which would return a Enumerable#lazy object. It also looks pretty good: xs.lazy_slice(1..-1).each { |x| puts x }
array.each_with_index {|x, i| puts x unless i.eql?0}

Looping through sections of an array in Ruby

I have an array containing a large number of contents
Names = ["one", "two", ......."forty"]
Now, I would like to loop through sections of the array. For example, from records 10 to 20, How can I go about this?
I tried this approach -
Names.each_with_index do |val,index|
break if index == 10
puts "#{val}"
end
In this way, I can print the first ten records. What should I do for getting next set of 10 names?
Any help is appreciated.
Cheers!
You can use each_slice to get successive sections of the array. For example:
require 'enumerator'
Names.each_slice(10) do |slice|
slice.each do |x|
puts x
end
puts "----"
end
You can e.g. use the each_slice method:
Names.each_slice(10) {|part|
puts part
}

Automatic counter in Ruby for each?

I want to use a for-each and a counter:
i=0
for blah in blahs
puts i.to_s + " " + blah
i+=1
end
Is there a better way to do it?
Note: I don't know if blahs is an array or a hash, but having to do blahs[i] wouldn't make it much sexier. Also I'd like to know how to write i++ in Ruby.
Technically, Matt's and Squeegy's answer came in first, but I'm giving best answer to paradoja so spread around the points a bit on SO. Also his answer had the note about versions, which is still relevant (as long as my Ubuntu 8.04 is using Ruby 1.8.6).
Should've used puts "#{i} #{blah}" which is a lot more succinct.
As people have said, you can use
each_with_index
but if you want indices with an iterator different to "each" (for example, if you want to map with an index or something like that) you can concatenate enumerators with the each_with_index method, or simply use with_index:
blahs.each_with_index.map { |blah, index| something(blah, index)}
blahs.map.with_index { |blah, index| something(blah, index) }
This is something you can do from ruby 1.8.7 and 1.9.
[:a, :b, :c].each_with_index do |item, i|
puts "index: #{i}, item: #{item}"
end
You can't do this with for. I usually like the more declarative call to each personally anyway. Partly because its easy to transition to other forms when you hits the limit of the for syntax.
Yes, it's collection.each to do loops, and then each_with_index to get the index.
You probably ought to read a Ruby book because this is fundamental Ruby and if you don't know it, you're going to be in big trouble (try: http://poignantguide.net/ruby/).
Taken from the Ruby source code:
hash = Hash.new
%w(cat dog wombat).each_with_index {|item, index|
hash[item] = index
}
hash #=> {"cat"=>0, "wombat"=>2, "dog"=>1}
If you don't have the new version of each_with_index, you can use the zip method to pair indexes with elements:
blahs = %w{one two three four five}
puts (1..blahs.length).zip(blahs).map{|pair|'%s %s' % pair}
which produces:
1 one
2 two
3 three
4 four
5 five
As to your question about doing i++, well, you cannot do that in Ruby. The i += 1 statement you had is exactly how you're supposed to do it.
If you want to get index of ruby for each, then you can use
.each_with_index
Here is an example to show how .each_with_index works:
range = ('a'..'z').to_a
length = range.length - 1
range.each_with_index do |letter, index|
print letter + " "
if index == length
puts "You are at last item"
end
end
This will print:
a b c d e f g h i j k l m n o p q r s t u v w x y z You are at last item
The enumerating enumerable series is pretty nice.
If blahs is a class that mixes in Enumerable, you should be able to do this:
blahs.each_with_index do |blah, i|
puts("#{i} #{blah}")
end

Resources