Ruby slicing not nil [duplicate] - ruby

This question already has answers here:
Array slicing in Ruby: explanation for illogical behaviour (taken from Rubykoans.com)
(10 answers)
Closed 7 years ago.
For a four-element array, [4] returns nil, but [4, 0] returns an empty array.
array = [:peanut, :butter, :and, :jelly]
array[4] # => nil
array[4, 0] # => []
array[5] # => nil
array[5, 0] # => nil
Why would [4, 0] not return nil just like [5, 0]?
Answer from Array slicing in Ruby: looking for explanation for illogical behaviour (taken from Rubykoans.com) =>
Graphical Explination of WHats Happening

It's a special case. From the official docs (the italics are mine):
For start and range cases the starting index is just
before an element. Additionally, an empty array is returned when the
starting index for an element range is at the end of the array.
a = [ "a", "b", "c", "d", "e" ]
# ...
# special cases
a[5] #=> nil
a[6, 1] #=> nil
a[5, 1] #=> []

Related

array[array.size..-1] doesn't return nil

I noticed a strange behavior when Range are used as Array subscript. (At least it's strange for me.)
a = [1,2,3]
=> [1, 2, 3]
a[3]
=> nil
a[3..-1]
=> []
a[4]
=> nil
a[4..-1]
=> nil
I thought a[3..-1] returns nil, but somehow it returns []. a[-3..-4] also returns [].
Could anyone explain why it returns [], when I use marginal values of range?
Because when range.begin == array.length, it always returns []. This is noted as a "special case" in the Ruby documentation:
a = [ "a", "b", "c", "d", "e" ]
# special cases
a[5] #=> nil
a[6, 1] #=> nil
a[5, 1] #=> []
a[5..10] #=> []

ary[start, length]. out of boundary number giving [ ] output? [duplicate]

This question already has answers here:
Is there some kind of unseen Array termination in Ruby?
(3 answers)
Closed 8 years ago.
While going over the Array class from the Ruby 2.0.0 docs, I noticed something I can't explain. The following is a direct example from the Ruby Docs:
a = [ "a", "b", "c", "d", "e" ]
a[6, 1] #=> nil
a[5] #=> nil
a[5, 1] #=> []
Could some one explain to me why a[5, 1] has the output [ ]?
The semantics of [] are the same as for slice when two integers are provided. As explained in http://ruby-doc.org/core-2.0/Array.html#method-i-slice, when the first integer points to the end of the array, the empty array will be returned.

Trying to understand Ruby arrays [duplicate]

This question already has answers here:
Array slicing in Ruby: explanation for illogical behaviour (taken from Rubykoans.com)
(10 answers)
Closed 9 years ago.
array = [:peanut, :butter, :and, :jelly]
Why does array[4,0] return [] and array[5,0] returns nil?
According to Array#[] documentation:
an empty array is returned when the starting index for an element
range is at the end of the array.
Returns nil if the index (or starting index) are out of range.
a = [ "a", "b", "c", "d", "e" ]
a[2] + a[0] + a[1] #=> "cab"
a[6] #=> nil
a[1, 2] #=> [ "b", "c" ]
a[1..3] #=> [ "b", "c", "d" ]
a[4..7] #=> [ "e" ]
a[6..10] #=> nil
a[-3, 3] #=> [ "c", "d", "e" ]
# special cases
a[5] #=> nil
a[6, 1] #=> nil
a[5, 1] #=> []
a[5..10] #=> []

what does [0..1] mean in Module.constants() method?

In the following code
Module.constants[0..1] # => [:object, :Module]
What does the [0..1] mean here?
0..1 is a range. It's syntactic sugar for the Ruby parser to create a Range object. You can do a lot with ranges, including simple iteration:
irb(main):003:0> (1..3).class
=> Range
irb(main):004:0> (1..3).each {|x| puts x}
1
2
3
=> 1..3
You can turn it into an Array, among other things:
irb(main):005:0> (1..3).to_a
=> [1, 2, 3]
When you use a Range as an Array#[] argument, it means you want all the elements whose index is in that range (inclusive):
irb(main):007:0> stuff = %w{a b c d e f}
=> ["a", "b", "c", "d", "e", "f"]
irb(main):008:0> range = 2..4
=> 2..4
irb(main):009:0> stuff[range]
=> ["c", "d", "e"]
Module.constants returns an array of all the constants defined in (i.e. namespaced to) the Module class (yes, Module is a class; see Module.class). The [0..1] says give me every element of the array from the 0th to the 1st. In general, if x is an array, then x[m..n] returns the subarray of x consisting of the elements from the mth to the nth. For example:
x = [36, 25, 16, 9, 4]
x[1..3] # => [25, 16, 9]

How to return a part of an array in Ruby?

With a list in Python I can return a part of it using the following code:
foo = [1,2,3,4,5,6]
bar = [10,20,30,40,50,60]
half = len(foo) / 2
foobar = foo[:half] + bar[half:]
Since Ruby does everything in arrays I wonder if there is something similar to that.
Yes, Ruby has very similar array-slicing syntax to Python. Here is the ri documentation for the array index method:
--------------------------------------------------------------- Array#[]
array[index] -> obj or nil
array[start, length] -> an_array or nil
array[range] -> an_array or nil
array.slice(index) -> obj or nil
array.slice(start, length) -> an_array or nil
array.slice(range) -> an_array or nil
------------------------------------------------------------------------
Element Reference---Returns the element at index, or returns a
subarray starting at start and continuing for length elements, or
returns a subarray specified by range. Negative indices count
backward from the end of the array (-1 is the last element).
Returns nil if the index (or starting index) are out of range.
a = [ "a", "b", "c", "d", "e" ]
a[2] + a[0] + a[1] #=> "cab"
a[6] #=> nil
a[1, 2] #=> [ "b", "c" ]
a[1..3] #=> [ "b", "c", "d" ]
a[4..7] #=> [ "e" ]
a[6..10] #=> nil
a[-3, 3] #=> [ "c", "d", "e" ]
# special cases
a[5] #=> nil
a[6, 1] #=> nil
a[5, 1] #=> []
a[5..10] #=> []
If you want to split/cut the array on an index i,
arr = arr.drop(i)
> arr = [1,2,3,4,5]
=> [1, 2, 3, 4, 5]
> arr.drop(2)
=> [3, 4, 5]
You can use slice() for this:
>> foo = [1,2,3,4,5,6]
=> [1, 2, 3, 4, 5, 6]
>> bar = [10,20,30,40,50,60]
=> [10, 20, 30, 40, 50, 60]
>> half = foo.length / 2
=> 3
>> foobar = foo.slice(0, half) + bar.slice(half, foo.length)
=> [1, 2, 3, 40, 50, 60]
By the way, to the best of my knowledge, Python "lists" are just efficiently implemented dynamically growing arrays. Insertion at the beginning is in O(n), insertion at the end is amortized O(1), random access is O(1).
Ruby 2.6 Beginless/Endless Ranges
(..1)
# or
(...1)
(1..)
# or
(1...)
[1,2,3,4,5,6][..3]
=> [1, 2, 3, 4]
[1,2,3,4,5,6][...3]
=> [1, 2, 3]
ROLES = %w[superadmin manager admin contact user]
ROLES[ROLES.index('admin')..]
=> ["admin", "contact", "user"]
another way is to use the range method
foo = [1,2,3,4,5,6]
bar = [10,20,30,40,50,60]
a = foo[0...3]
b = bar[3...6]
print a + b
=> [1, 2, 3, 40, 50 , 60]
I like ranges for this:
def first_half(list)
list[0...(list.length / 2)]
end
def last_half(list)
list[(list.length / 2)..list.length]
end
However, be very careful about whether the endpoint is included in your range. This becomes critical on an odd-length list where you need to choose where you're going to break the middle. Otherwise you'll end up double-counting the middle element.
The above example will consistently put the middle element in the last half.

Resources