Ruby 'Range.Last' Does Not Give the Last Value. Why

Ruby 'Range.last' does not give the last value. Why?

This is by design. The Ruby 2.0 documentation is more specific:

Note that with no arguments last will return the object that defines the end of the range even if exclude_end? is true.

(10..20).last      #=> 20
(10...20).last #=> 20
(10..20).last(3) #=> [18, 19, 20]
(10...20).last(3) #=> [17, 18, 19]

Ruby array only storing last value, not all values

In your index action, change the line:

@products = Product.where(category_id: category.id).take(1)

To:

@products << Product.where(category_id: category.id).take(1)

UPDATE:

Since take(1) will return an object in array, you need to simply change it to:

@products << Product.where(category_id: category.id).take

Why is (10..20).last the same as (10...20).last

I'll answer your question with a question: what is the last value of 0.0...1.0?

In general, not every Range is enumerable. For such ranges with an excluded end, there really is no meaningful last value other than the value used to define the end of the range.

Note also that you can enumerate inclusive ranges where last is not the last value enumerated!

(0..3.2).to_a.last
# 3
(0..3.2).last
# 3.2
(0..Float::INFINITY).to_a.last
# don't wait up for this one

The motivation of the design is that "the value used to define the end of a range" is not identical to "the last value enumerated by a range". last gives you the former.

Ruby - Last value of a isn't printed

return controls program flow, calling it will exit the current method and pass the value of a into whatever expression called it.

Usually you would not write a method with an unconditional return and more code afterward, because that code is not reachable. The puts in your example will never be called. Just move it to before the return expression if you want it to run.

What was the last version of Ruby where array range never returned nil?

I think it's 1.2.x.

The oldest Ruby documentation I could find was was for Ruby 1.2. It says this about Array#[]:

self[start..end]

Returns an array containing the objects from start to end, including both ends. if end is laeger[sic] than the length of the array, it will be rounded to the length. And if start is larger than end, this method returns empty array ([]).

So in 1.2, it always returns an array.

The next-oldest documentation I could find was for Ruby 1.6. It says:

arr[anInteger] -> anObject or nil
arr[start, length] -> aSubArray or nil
arr[aRange] -> aSubArray or nil

Element Reference-Returns the element at index anInteger, or returns a subarray starting at index start and continuing for length elements, or returns a subarray specified by aRange. Negative indices count backward from the end of the array (-1 is the last element). Returns nil if any indices are out of range.

So that narrows it down a lot. Then I decided to go straight to the source. In Ruby 1.2, Array#[] is called ary_aref in array.c. If the argument is a range, it calls beg_len to get the beginning index and the length of the subsequence, and then calls ary_subseq with those arguments. Long story short, ary_subseq always returns an array, never nil.

Next I tried Ruby 1.3, where Array#[] is now called rb_ary_aref. Lo and behold, we see this (406–414):

/* check if idx is Range */
switch (rb_range_beg_len(arg1, &beg, &len, RARRAY(ary)->len, 0)) {
case Qfalse:
break;
case Qnil:
return Qnil;
default:
return rb_ary_subary(ary, beg, len);
}

I think that speaks for itself: If the argument is out of range, return nil.

Since I'm terrible at C, I went and checked the Ruby 1.6 source (since we know from the documentation that it has the nil behavior) and found that its implementation is the same.

I'm pretty confident, then, that Ruby 1.2.x is the last Ruby that returned an empty array, and 1.3.x is the first Ruby that returned nil.

Ruby 1.2, by the way, was released in 1998.

Last element of the ruby array is nil

Array.new creates a new array, filling it with the quantity of elements you specified. Array.new(3) is the same as [nil, nil, nil]. Array.new(2, 'a') is the same as ['a', 'a'].

You then use array.insert which adds instead of replaces the elements. You could use array[i-1] = gets.chomp() to set the values, but there's really no reason to initialize the array this way at all.

A "more Ruby" way to write this all would be:

puts 'How many stocks do you want to track ?'
num_stocks = gets.chomp
puts "Please enter #{num_stocks} stock symbols: "

array = 1.upto(num_stocks.to_i).map do
gets.chomp
end

puts "Stock symbols entered ... #{array}"

EDIT:
Also, it’s worth mentioning that in Ruby, arrays are not a fixed size. You can add and remove elements from them as you please. If I had to guess, you’re used to languages like C, where you have to define the size of your array up front and then it’s just that size forever (that’s what I’m guessing you were trying to do anyways).

And another thing, in Ruby it’s not very common to use Array.new. Most times people just define an array by typing an array literal.

array = [1,2,3]

A ruby array is more like a List in other languages. It supports push (though << is a more common method for adding to an array), pop, and other list-like features.

Ruby for loop only using last value

The problem is that you are re-assigning @facilities on each iteration of the loop. I think you want something more like:

@facilities = []
for a in @activities
@facilities << Facility.find(a.facility_id)
end

This might be better written as

@facilities = @activities.map {|a| Facility.find(a.facility_id) }

But, preferably, you've defined an association for :facility

@facilities = @activities.map {|a| a.facility}

Ruby recursion through array not getting to last value

It's the second-last ")" that return immediately before it reach the last ")". Note that return in lambda will also return from the parent function. This code should work:

UPDATE: I think an array is not sufficient to get the data since it lacks the link between its member to the parent container. A tree data structure is required to store the information and a child can link with parent through function parent here. I rewrite the code, and this returns result as expected:

class Node
attr_accessor :parent, :children, :values
def initialize
@children = []
@parent = nil
@values = []
end

def add_child(child)
child.parent = self
@children << child
end

def add_value(value)
@values << value
end

def to_a
result = values.clone
@children.each do |child|
result << child.to_a
end
result
end
end

def set_execution_order(value)
_set_execution_order = lambda do |tokens, node|
token = tokens.shift
case token
when nil
return node
when "("
child = Node.new
node.add_child(child)
_set_execution_order[tokens, child]
when ")"
_set_execution_order[tokens, node.parent]
else
node.add_value(token)
return _set_execution_order[tokens, node]
end
end

root = Node.new
_set_execution_order[value, root]
root
end

set_execution_order(["(", 1, "(", 2, 3, ")", 4, "(", 5, 6, ")", ")"]).to_a #returns => [[1, 4, [2, 3], [5, 6]]]

All but last element of Ruby array

Perhaps...

a = t               # => [1, 2, 3, 4]
a.first a.size - 1 # => [1, 2, 3]

or

a.take 3

or

a.first 3

or

a.pop

which will return the last and leave the array with everything before it

or make the computer work for its dinner:

a.reverse.drop(1).reverse

or

class Array
def clip n=1
take size - n
end
end
a # => [1, 2, 3, 4]
a.clip # => [1, 2, 3]
a = a + a # => [1, 2, 3, 4, 1, 2, 3, 4]
a.clip 2 # => [1, 2, 3, 4, 1, 2]

How do I destructure a range in Ruby?

No, Until I am proven incorrect by Cary Swoveland, Weekly World News or another tabloid, I'll continue believing without any evidence that the answer is "no"; but it's easy enough to make.

module RangeWithBounds
refine Range do
def bounds
[self.begin, self.end]
end
end
end

module Test
using RangeWithBounds
r = (1..10)
b, e = *r.bounds
puts "#{b}..#{e}"
end

Then again, I'd just write "#{r.begin.number_to_currency}..#{r.end.number_to_currency}" in the first place.



Related Topics



Leave a reply



Submit