Class: Array
Overview
Arrays are ordered, integer-indexed collections of any object.
Array indexing starts at 0, as in C or Java. A negative index is assumed to be relative to the end of the array---that is, an index of -1 indicates the last element of the array, -2 is the next to last element in the array, and so on.
Creating Arrays
A new array can be created by using the literal constructor []
. Arrays can contain different types of objects. For example, the array below contains an Integer, a String and a Float:
ary = [1, "two", 3.0] #=> [1, "two", 3.0]
An array can also be created by explicitly calling Array.new with zero, one (the initial size of the Array) or two arguments (the initial size and a default object).
ary = Array.new #=> []
Array.new(3) #=> [nil, nil, nil]
Array.new(3, true) #=> [0, 0, 0]
Note that the second argument populates the array with references to the same object. Therefore, it is only recommended in cases when you need to instantiate arrays with natively immutable objects such as Symbols, numbers, true or false.
To create an array with separate objects a block can be passed instead. This method is safe to use with mutable objects such as hashes, strings or other arrays:
Array.new(4) { Hash.new } #=> [{}, {}, {}, {}]
This is also a quick way to build up multi-dimensional arrays:
empty_table = Array.new(3) { Array.new(3) }
#=> [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
An array can also be created by using the Array() method, provided by Kernel, which calls #to_ary or #to_a on it's argument.
Array(=> "a", :b => "b") #=> [[:a, "a"], [:b, "b"]]
Example Usage
In addition to the methods it mixes in through the Enumerable module, the Array class has proprietary methods for accessing, searching and otherwise manipulating arrays.
Some of the more common ones are illustrated below.
Accessing Elements
Elements in an array can be retrieved using the Array#[] method. It can take a single integer argument (a numeric index), a pair of arguments (start and length) or a range.
arr = [1, 2, 3, 4, 5, 6]
arr[2] #=> 3
arr[100] #=> nil
arr[-3] #=> 4
arr[2, 3] #=> [3, 4, 5]
arr[1..4] #=> [2, 3, 4, 5]
Another way to access a particular array element is by using the #at method
arr.at(0) #=> 1
The #slice method works in an identical manner to Array#[].
To raise an error for indices outside of the array bounds or else to provide a default value when that happens, you can use #fetch.
arr = ['a', 'b', 'c', 'd', 'e', 'f']
arr.fetch(100) #=> IndexError: index 100 outside of array bounds: -6...6
arr.fetch(100, "oops") #=> "oops"
The special methods #first and #last will return the first and last elements of an array, respectively.
arr.first #=> 1
arr.last #=> 6
To return the first n
elements of an array, use #take
arr.take(3) #=> [1, 2, 3]
#drop does the opposite of #take, by returning the elements after n
elements have been dropped:
arr.drop(3) #=> [4, 5, 6]
Obtaining Information about an Array
Arrays keep track of their own length at all times. To query an array about the number of elements it contains, use #length, #count or #size.
browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
browsers.length #=> 5
browsers.count #=> 5
To check whether an array contains any elements at all
browsers.empty? #=> false
To check whether a particular item is included in the array
browsers.include?('Konqueror') #=> false
Adding Items to Arrays
Items can be added to the end of an array by using either #push or #<<
arr = [1, 2, 3, 4]
arr.push(5) #=> [1, 2, 3, 4, 5]
arr << 6 #=> [1, 2, 3, 4, 5, 6]
#unshift will add a new item to the beginning of an array.
arr.unshift(0) #=> [0, 1, 2, 3, 4, 5, 6]
With #insert you can add a new element to an array at any position.
arr.insert(3, 'apple') #=> [0, 1, 2, 'apple', 3, 4, 5, 6]
Using the #insert method, you can also insert multiple values at once:
arr.insert(3, 'orange', 'pear', 'grapefruit')
#=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
Removing Items from an Array
The method #pop removes the last element in an array and returns it:
arr = [1, 2, 3, 4, 5, 6]
arr.pop #=> 6
arr #=> [1, 2, 3, 4, 5]
To retrieve and at the same time remove the first item, use #shift:
arr.shift #=> 1
arr #=> [2, 3, 4, 5]
To delete an element at a particular index:
arr.delete_at(2) #=> 4
arr #=> [2, 3, 5]
To delete a particular element anywhere in an array, use #delete:
arr = [1, 2, 2, 3]
arr.delete(2) #=> [1, 3]
A useful method if you need to remove nil
values from an array is #compact:
arr = ['foo', 0, nil, 'bar', 7, 'baz', nil]
arr.compact #=> ['foo', 0, 'bar', 7, 'baz']
arr #=> ['foo', 0, nil, 'bar', 7, 'baz', nil]
arr.compact! #=> ['foo', 0, 'bar', 7, 'baz']
arr #=> ['foo', 0, 'bar', 7, 'baz']
Another common need is to remove duplicate elements from an array.
It has the non-destructive #uniq, and destructive method #uniq!
arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]
Iterating over Arrays
Like all classes that include the Enumerable module, Array has an each method, which defines what elements should be iterated over and how. In case of Array's #each, all elements in the Array instance are yielded to the supplied block in sequence.
Note that this operation leaves the array unchanged.
arr = [1, 2, 3, 4, 5]
arr.each { |a| print a -= 10, " " }
# prints: -9 -8 -7 -6 -5
#=> [1, 2, 3, 4, 5]
Another sometimes useful iterator is #reverse_each which will iterate over the elements in the array in reverse order.
words = %w[rats live on no evil star]
str = ""
words.reverse_each { |word| str += "#{word.reverse} " }
str #=> "rats live on no evil star "
The #map method can be used to create a new array based on the original array, but with the values modified by the supplied block:
arr.map { |a| 2*a } #=> [2, 4, 6, 8, 10]
arr #=> [1, 2, 3, 4, 5]
arr.map! { |a| a**2 } #=> [1, 4, 9, 16, 25]
arr #=> [1, 4, 9, 16, 25]
Selecting Items from an Array
Elements can be selected from an array according to criteria defined in a block. The selection can happen in a destructive or a non-destructive manner. While the destructive operations will modify the array they were called on, the non-destructive methods usually return a new array with the selected elements, but leave the original array unchanged.
Non-destructive Selection
arr = [1, 2, 3, 4, 5, 6]
arr.select { |a| a > 3 } #=> [4, 5, 6]
arr.reject { |a| a < 3 } #=> [4, 5, 6]
arr.drop_while { |a| a < 4 } #=> [4, 5, 6]
arr #=> [1, 2, 3, 4, 5, 6]
Destructive Selection
#select! and #reject! are the corresponding destructive methods to #select and #reject
Similar to #select vs. #reject, #delete_if and #keep_if have the exact opposite result when supplied with the same block:
arr.delete_if { |a| a < 4 } #=> [4, 5, 6]
arr #=> [4, 5, 6]
arr = [1, 2, 3, 4, 5, 6]
arr.keep_if { |a| a < 4 } #=> [1, 2, 3]
arr #=> [1, 2, 3]
Class Method Summary collapse
-
.[] ⇒ Object
Returns a new array populated with the given objects.
-
.try_convert(obj) ⇒ Array?
Tries to convert
obj
into an array, usingto_ary
method.
Instance Method Summary collapse
-
#&(other_ary) ⇒ Object
Set Intersection --- Returns a new array containing elements common to the two arrays, excluding any duplicates.
-
#* ⇒ Object
Repetition --- With a String argument, equivalent to
ary.join(str)
. -
#+(other_ary) ⇒ Object
Concatenation --- Returns a new array built by concatenating the two arrays together to produce a third array.
-
#-(other_ary) ⇒ Object
Array Difference.
-
#<<(obj) ⇒ Object
Append---Pushes the given object on to the end of this array.
-
#<=>(other_ary) ⇒ -1, ...
Comparison --- Returns an integer (
-1
,0
, or+1
) if this array is less than, equal to, or greater thanother_ary
. -
#==(other_ary) ⇒ Boolean
Equality --- Two arrays are equal if they contain the same number of elements and if each element is equal to (according to Object#==) the corresponding element in
other_ary
. -
#[] ⇒ Object
Element Reference --- Returns the element at
index
, or returns a subarray starting at thestart
index and continuing forlength
elements, or returns a subarray specified byrange
of indices. -
#[]= ⇒ Object
Element Assignment --- Sets the element at
index
, or replaces a subarray from thestart
index forlength
elements, or replaces a subarray specified by therange
of indices. -
#assoc(obj) ⇒ nil
Searches through an array whose elements are also arrays comparing
obj
with the first element of each contained array usingobj.==
. -
#at(index) ⇒ Object?
Returns the element at
index
. -
#bsearch {|x| ... } ⇒ Object
By using binary search, finds a value from this array which meets the given condition in O(log n) where n is the size of the array.
-
#clear ⇒ Object
Removes all elements from
self
. -
#collect ⇒ Object
Invokes the given block once for each element of
self
. -
#collect! ⇒ Object
Invokes the given block once for each element of
self
, replacing the element with the value returned by the block. -
#combination ⇒ Object
When invoked with a block, yields all combinations of length
n
of elements from the array and then returns the array itself. -
#compact ⇒ Object
Returns a copy of
self
with allnil
elements removed. -
#compact! ⇒ nil
Removes
nil
elements from the array. -
#concat(other_ary) ⇒ Object
Appends the elements of
other_ary
toself
. -
#count ⇒ Object
Returns the number of elements.
-
#cycle ⇒ Object
Calls the given block for each element
n
times or forever ifnil
is given. -
#delete ⇒ Object
Deletes all items from
self
that are equal toobj
. -
#delete_at(index) ⇒ Object?
Deletes the element at the specified
index
, returning that element, ornil
if theindex
is out of range. -
#delete_if ⇒ Object
Deletes every element of
self
for which block evaluates totrue
. -
#drop(n) ⇒ Object
Drops first
n
elements fromary
and returns the rest of the elements in an array. -
#drop_while ⇒ Object
Drops elements up to, but not including, the first element for which the block returns
nil
orfalse
and returns an array containing the remaining elements. -
#each ⇒ Object
Calls the given block once for each element in
self
, passing that element as a parameter. -
#each_index ⇒ Object
Same as Array#each, but passes the
index
of the element instead of the element itself. -
#empty? ⇒ Boolean
Returns
true
ifself
contains no elements. -
#eql?(other) ⇒ Boolean
Returns
true
ifself
andother
are the same object, or are both arrays with the same content. -
#fetch ⇒ Object
Tries to return the element at position
index
, but throws an IndexError exception if the referencedindex
lies outside of the array bounds. -
#fill ⇒ Object
The first three forms set the selected elements of
self
(which may be the entire array) toobj
. -
#find_index ⇒ Object
Returns the index of the first object in
ary
such that the object is==
toobj
. -
#first ⇒ Object
Returns the first element, or the first
n
elements, of the array. -
#flatten ⇒ Object
Returns a new array that is a one-dimensional flattening of
self
(recursively). -
#flatten! ⇒ Object
Flattens
self
in place. -
#frozen? ⇒ Boolean
Return
true
if this array is frozen (or temporarily frozen while being sorted). -
#hash ⇒ Fixnum
Compute a hash-code for this array.
-
#include?(object) ⇒ Boolean
Returns
true
if the givenobject
is present inself
(that is, if any object==
object
), otherwise returnsfalse
. -
#index ⇒ Object
Returns the index of the first object in
ary
such that the object is==
toobj
. -
#initialize ⇒ Object
constructor
Returns a new array.
-
#replace(other_ary) ⇒ Object
Replaces the contents of
self
with the contents ofother_ary
, truncating or expanding if necessary. -
#insert(index, obj...) ⇒ Object
Inserts the given values before the element with the given
index
. -
#inspect ⇒ Object
(also: #to_s)
Creates a string representation of
self
. -
#join(separator = $,) ⇒ String
Returns a string created by converting each element of the array to a string, separated by the given
separator
. -
#keep_if ⇒ Object
Deletes every element of
self
for which the given block evaluates tofalse
. -
#last ⇒ Object
Returns the last element(s) of
self
. -
#length ⇒ Integer
(also: #size)
Returns the number of elements in
self
. -
#map ⇒ Object
Invokes the given block once for each element of
self
. -
#map! ⇒ Object
Invokes the given block once for each element of
self
, replacing the element with the value returned by the block. -
#pack ⇒ Object
Packs the contents of arr into a binary sequence according to the directives in aTemplateString (see the table below) Directives "A," "a," and "Z" may be followed by a count, which gives the width of the resulting field.
-
#permutation ⇒ Object
When invoked with a block, yield all permutations of length
n
of the elements of the array, then return the array itself. -
#pop ⇒ Object
Removes the last element from
self
and returns it, ornil
if the array is empty. -
#product ⇒ Object
Returns an array of all combinations of elements from all arrays.
-
#push(obj, ...) ⇒ Object
Append --- Pushes the given object(s) on to the end of this array.
-
#rassoc(obj) ⇒ nil
Searches through the array whose elements are also arrays.
-
#reject ⇒ Object
Returns a new array containing the items in
self
for which the given block is nottrue
. -
#reject! ⇒ Object
Equivalent to Array#delete_if, deleting elements from
self
for which the block evaluates totrue
, but returnsnil
if no changes were made. -
#repeated_combination ⇒ Object
When invoked with a block, yields all repeated combinations of length
n
of elements from the array and then returns the array itself. -
#repeated_permutation ⇒ Object
When invoked with a block, yield all repeated permutations of length
n
of the elements of the array, then return the array itself. -
#replace(other_ary) ⇒ Object
Replaces the contents of
self
with the contents ofother_ary
, truncating or expanding if necessary. -
#reverse ⇒ Object
Returns a new array containing
self
's elements in reverse order. -
#reverse! ⇒ Object
Reverses
self
in place. -
#reverse_each ⇒ Object
Same as Array#each, but traverses
self
in reverse order. -
#rindex ⇒ Object
Returns the index of the last object in
self
==
toobj
. -
#rotate(count = 1) ⇒ Object
Returns a new array by rotating
self
so that the element atcount
is the first element of the new array. -
#rotate!(count = 1) ⇒ Object
Rotates
self
in place so that the element atcount
comes first, and returnsself
. -
#sample ⇒ Object
Choose a random element or
n
random elements from the array. -
#select ⇒ Object
Returns a new array containing all elements of
ary
for which the givenblock
returns a true value. -
#select! ⇒ Object
Invokes the given block passing in successive elements from
self
, deleting elements for which the block returns afalse
value. -
#shift ⇒ Object
Removes the first element of
self
and returns it (shifting all other elements down by one). -
#shuffle ⇒ Object
Returns a new array with elements of
self
shuffled. -
#shuffle! ⇒ Object
Shuffles elements in
self
in place. -
#slice ⇒ Object
Element Reference --- Returns the element at
index
, or returns a subarray starting at thestart
index and continuing forlength
elements, or returns a subarray specified byrange
of indices. -
#slice! ⇒ Object
Deletes the element(s) given by an
index
(optionally up tolength
elements) or by arange
. -
#sort ⇒ Object
Returns a new array created by sorting
self
. -
#sort! ⇒ Object
Sorts
self
in place. -
#sort_by! ⇒ Object
Sorts
self
in place using a set of keys generated by mapping the values inself
through the given block. -
#take(n) ⇒ Object
Returns first
n
elements from the array. -
#take_while ⇒ Object
Passes elements to the block until the block returns
nil
orfalse
, then stops iterating and returns an array of all prior elements. -
#to_a ⇒ Object
Returns
self
. -
#to_ary ⇒ Object
Returns
self
. -
#transpose ⇒ Object
Assumes that
self
is an array of arrays and transposes the rows and columns. -
#uniq ⇒ Object
Returns a new array by removing duplicate values in
self
. -
#uniq! ⇒ Object
Removes duplicate elements from
self
. -
#unshift(obj, ...) ⇒ Object
Prepends objects to the front of
self
, moving other elements upwards. -
#values_at(selector, ...) ⇒ Object
Returns an array containing the elements in
self
corresponding to the givenselector
(s). -
#zip ⇒ Object
Converts any arguments to arrays, then merges elements of
self
with corresponding elements from each argument. -
#|(other_ary) ⇒ Object
Set Union --- Returns a new array by joining
ary
withother_ary
, excluding any duplicates.
Methods included from Enumerable
#all?, #any?, #chunk, #collect_concat, #detect, #each_cons, #each_entry, #each_slice, #each_with_index, #each_with_object, #entries, #find, #find_all, #flat_map, #grep, #group_by, #inject, #lazy, #max, #max_by, #member?, #min, #min_by, #minmax, #minmax_by, #none?, #one?, #partition, #reduce, #slice_before, #sort_by
Constructor Details
#new(size = 0, obj = nil) ⇒ Object #new(array) ⇒ Object #new(size) {|index| ... } ⇒ Object
Returns a new array.
In the first form, if no arguments are sent, the new array will be empty. When a size
and an optional obj
are sent, an array is created with size
copies of obj
. Take notice that all elements will reference the same object obj
.
The second form creates a copy of the array passed as a parameter (the array is generated by calling to_ary on the parameter).
first_array = ["Matz", "Guido"]
second_array = Array.new(first_array) #=> ["Matz", "Guido"]
first_array.equal? second_array #=> false
In the last form, an array of the given size is created. Each element in this array is created by passing the element's index to the given block and storing the return value.
Array.new(3){ |index| index ** 2 }
# => [0, 1, 4]
Common gotchas
When sending the second parameter, the same object will be used as the value for all the array elements:
a = Array.new(2, Hash.new)
# => [{}, {}]
a[0]['cat'] = 'feline'
a # => [{"cat"=>"feline"}, {"cat"=>"feline"}]
a[1]['cat'] = 'Felix'
a # => [{"cat"=>"Felix"}, {"cat"=>"Felix"}]
Since all the Array elements store the same hash, changes to one of them will affect them all.
If multiple copies are what you want, you should use the block version which uses the result of that block each time an element of the array needs to be initialized:
a = Array.new(2) { Hash.new }
a[0]['cat'] = 'feline'
a # => [{"cat"=>"feline"}, {}]
644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 |
# File 'array.c', line 644
static VALUE
rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
{
long len;
VALUE size, val;
rb_ary_modify(ary);
if (argc == 0) {
if (ARY_OWNS_HEAP_P(ary) && RARRAY_PTR(ary)) {
xfree(RARRAY_PTR(ary));
}
rb_ary_unshare_safe(ary);
FL_SET_EMBED(ary);
ARY_SET_EMBED_LEN(ary, 0);
if (rb_block_given_p()) {
rb_warning("given block not used");
}
return ary;
}
rb_scan_args(argc, argv, "02", &size, &val);
if (argc == 1 && !FIXNUM_P(size)) {
val = rb_check_array_type(size);
if (!NIL_P(val)) {
rb_ary_replace(ary, val);
return ary;
}
}
len = NUM2LONG(size);
if (len < 0) {
rb_raise(rb_eArgError, "negative array size");
}
if (len > ARY_MAX_SIZE) {
rb_raise(rb_eArgError, "array size too big");
}
rb_ary_modify(ary);
ary_resize_capa(ary, len);
if (rb_block_given_p()) {
long i;
if (argc == 2) {
rb_warn("block supersedes default value argument");
}
for (i=0; i<len; i++) {
rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
ARY_SET_LEN(ary, i + 1);
}
}
else {
memfill(RARRAY_PTR(ary), len, val);
ARY_SET_LEN(ary, len);
}
return ary;
}
|
Class Method Details
.[] ⇒ Object
707 708 709 710 711 712 713 714 715 716 717 |
# File 'array.c', line 707
static VALUE
rb_ary_s_create(int argc, VALUE *argv, VALUE klass)
{
VALUE ary = ary_new(klass, argc);
if (argc > 0 && argv) {
MEMCPY(RARRAY_PTR(ary), argv, VALUE, argc);
ARY_SET_LEN(ary, argc);
}
return ary;
}
|
.try_convert(obj) ⇒ Array?
Tries to convert obj
into an array, using to_ary
method. Returns the converted array or nil
if obj
cannot be converted for any reason. This method can be used to check if an argument is an array.
Array.try_convert([1]) #=> [1]
Array.try_convert("1") #=> nil
if tmp = Array.try_convert(arg)
# the argument is an array
elsif tmp = String.try_convert(arg)
# the argument is a string
end
582 583 584 585 586 |
# File 'array.c', line 582
static VALUE
rb_ary_s_try_convert(VALUE dummy, VALUE ary)
{
return rb_check_array_type(ary);
}
|
Instance Method Details
#&(other_ary) ⇒ Object
Set Intersection --- Returns a new array containing elements common to the two arrays, excluding any duplicates.
It compares elements using their #hash and #eql? methods for efficiency.
[ 1, 1, 3, 5 ] & [ 1, 2, 3 ] #=> [ 1, 3 ]
[ 'a', 'b', 'b', 'z' ] & [ 'a', 'b', 'c' ] #=> [ 'a', 'b' ]
See also Array#uniq.
3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 |
# File 'array.c', line 3847
static VALUE
rb_ary_and(VALUE ary1, VALUE ary2)
{
VALUE hash, ary3, v;
st_data_t vv;
long i;
ary2 = to_ary(ary2);
ary3 = rb_ary_new2(RARRAY_LEN(ary1) < RARRAY_LEN(ary2) ?
RARRAY_LEN(ary1) : RARRAY_LEN(ary2));
hash = ary_make_hash(ary2);
if (RHASH_EMPTY_P(hash))
return ary3;
for (i=0; i<RARRAY_LEN(ary1); i++) {
vv = (st_data_t)(v = rb_ary_elt(ary1, i));
if (st_delete(RHASH_TBL(hash), &vv, 0)) {
rb_ary_push(ary3, v);
}
}
ary_recycle_hash(hash);
return ary3;
}
|
#*(int) ⇒ Object #*(str) ⇒ Object
Repetition --- With a String argument, equivalent to ary.join(str)
.
Otherwise, returns a new array built by concatenating the int
copies of self
.
[ 1, 2, 3 ] * 3 #=> [ 1, 2, 3, 1, 2, 3, 1, 2, 3 ]
[ 1, 2, 3 ] * "," #=> "1,2,3"
3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 |
# File 'array.c', line 3411
static VALUE
rb_ary_times(VALUE ary, VALUE times)
{
VALUE ary2, tmp, *ptr, *ptr2;
long t, len;
tmp = rb_check_string_type(times);
if (!NIL_P(tmp)) {
return rb_ary_join(ary, tmp);
}
len = NUM2LONG(times);
if (len == 0) {
ary2 = ary_new(rb_obj_class(ary), 0);
goto out;
}
if (len < 0) {
rb_raise(rb_eArgError, "negative argument");
}
if (ARY_MAX_SIZE/len < RARRAY_LEN(ary)) {
rb_raise(rb_eArgError, "argument too big");
}
len *= RARRAY_LEN(ary);
ary2 = ary_new(rb_obj_class(ary), len);
ARY_SET_LEN(ary2, len);
ptr = RARRAY_PTR(ary);
ptr2 = RARRAY_PTR(ary2);
t = RARRAY_LEN(ary);
if (0 < t) {
MEMCPY(ptr2, ptr, VALUE, t);
while (t <= len/2) {
MEMCPY(ptr2+t, ptr2, VALUE, t);
t *= 2;
}
if (t < len) {
MEMCPY(ptr2+t, ptr2, VALUE, len-t);
}
}
out:
OBJ_INFECT(ary2, ary);
return ary2;
}
|
#+(other_ary) ⇒ Object
Concatenation --- Returns a new array built by concatenating the two arrays together to produce a third array.
[ 1, 2, 3 ] + [ 4, 5 ] #=> [ 1, 2, 3, 4, 5 ]
a = [ "a", "b", "c" ]
a + [ "d", "e", "f" ]
a #=> [ "a", "b", "c", "d", "e", "f" ]
See also Array#concat.
3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 |
# File 'array.c', line 3353
VALUE
rb_ary_plus(VALUE x, VALUE y)
{
VALUE z;
long len;
y = to_ary(y);
len = RARRAY_LEN(x) + RARRAY_LEN(y);
z = rb_ary_new2(len);
MEMCPY(RARRAY_PTR(z), RARRAY_PTR(x), VALUE, RARRAY_LEN(x));
MEMCPY(RARRAY_PTR(z) + RARRAY_LEN(x), RARRAY_PTR(y), VALUE, RARRAY_LEN(y));
ARY_SET_LEN(z, len);
return z;
}
|
#-(other_ary) ⇒ Object
Array Difference
Returns a new array that is a copy of the original array, removing any items that also appear in other_ary
.
It compares elements using their #hash and #eql? methods for efficiency.
[ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ] #=> [ 3, 3, 5 ]
If you need set-like behavior, see the library class Set.
3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 |
# File 'array.c', line 3813
static VALUE
rb_ary_diff(VALUE ary1, VALUE ary2)
{
VALUE ary3;
volatile VALUE hash;
long i;
hash = ary_make_hash(to_ary(ary2));
ary3 = rb_ary_new();
for (i=0; i<RARRAY_LEN(ary1); i++) {
if (st_lookup(RHASH_TBL(hash), RARRAY_PTR(ary1)[i], 0)) continue;
rb_ary_push(ary3, rb_ary_elt(ary1, i));
}
ary_recycle_hash(hash);
return ary3;
}
|
#<<(obj) ⇒ Object
Append---Pushes the given object on to the end of this array. This expression returns the array itself, so several appends may be chained together.
[ 1, 2 ] << "c" << "d" << [ 3, 4 ]
#=> [ 1, 2, "c", "d", [ 3, 4 ] ]
822 823 824 825 826 827 828 829 830 831 |
# File 'array.c', line 822
VALUE
rb_ary_push(VALUE ary, VALUE item)
{
long idx = RARRAY_LEN(ary);
ary_ensure_room_for_push(ary, 1);
RARRAY_PTR(ary)[idx] = item;
ARY_SET_LEN(ary, idx + 1);
return ary;
}
|
#<=>(other_ary) ⇒ -1, ...
Comparison --- Returns an integer (-1
, 0
, or +1
) if this array is less than, equal to, or greater than other_ary
.
Each object in each array is compared (using the <=> operator).
Arrays are compared in an "element-wise" manner; the first two elements that are not equal will determine the return value for the whole comparison.
If all the values are equal, then the return is based on a comparison of the array lengths. Thus, two arrays are "equal" according to Array#<=> if, and only if, they have the same length and the value of each element is equal to the value of the corresponding element in the other array.
[ "a", "a", "c" ] <=> [ "a", "b", "c" ] #=> -1
[ 1, 2, 3, 4, 5, 6 ] <=> [ 1, 2 ] #=> +1
3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 |
# File 'array.c', line 3722
VALUE
rb_ary_cmp(VALUE ary1, VALUE ary2)
{
long len;
VALUE v;
ary2 = rb_check_array_type(ary2);
if (NIL_P(ary2)) return Qnil;
if (ary1 == ary2) return INT2FIX(0);
v = rb_exec_recursive_paired(recursive_cmp, ary1, ary2, ary2);
if (v != Qundef) return v;
len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2);
if (len == 0) return INT2FIX(0);
if (len > 0) return INT2FIX(1);
return INT2FIX(-1);
}
|
#==(other_ary) ⇒ Boolean
Equality --- Two arrays are equal if they contain the same number of elements and if each element is equal to (according to Object#==) the corresponding element in other_ary
.
[ "a", "c" ] == [ "a", "c", 7 ] #=> false
[ "a", "c", 7 ] == [ "a", "c", 7 ] #=> true
[ "a", "c", 7 ] == [ "a", "d", "f" ] #=> false
3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 |
# File 'array.c', line 3573
static VALUE
rb_ary_equal(VALUE ary1, VALUE ary2)
{
if (ary1 == ary2) return Qtrue;
if (!RB_TYPE_P(ary2, T_ARRAY)) {
if (!rb_respond_to(ary2, rb_intern("to_ary"))) {
return Qfalse;
}
return rb_equal(ary2, ary1);
}
if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
return rb_exec_recursive_paired(recursive_equal, ary1, ary2, ary2);
}
|
#[](index) ⇒ Object? #[](start, length) ⇒ nil #[](range) ⇒ nil #slice(index) ⇒ Object? #slice(start, length) ⇒ nil #slice(range) ⇒ nil
Element Reference --- Returns the element at index
, or returns a subarray starting at the start
index and continuing for length
elements, or returns a subarray specified by range
of indices.
Negative indices count backward from the end of the array (-1 is the last element). 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.
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] #=> []
1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 |
# File 'array.c', line 1163
VALUE
rb_ary_aref(int argc, VALUE *argv, VALUE ary)
{
VALUE arg;
long beg, len;
if (argc == 2) {
beg = NUM2LONG(argv[0]);
len = NUM2LONG(argv[1]);
if (beg < 0) {
beg += RARRAY_LEN(ary);
}
return rb_ary_subseq(ary, beg, len);
}
if (argc != 1) {
rb_scan_args(argc, argv, "11", NULL, NULL);
}
arg = argv[0];
/* special case - speeding up */
if (FIXNUM_P(arg)) {
return rb_ary_entry(ary, FIX2LONG(arg));
}
/* check if idx is Range */
switch (rb_range_beg_len(arg, &beg, &len, RARRAY_LEN(ary), 0)) {
case Qfalse:
break;
case Qnil:
return Qnil;
default:
return rb_ary_subseq(ary, beg, len);
}
return rb_ary_entry(ary, NUM2LONG(arg));
}
|
#[]=(index) ⇒ Object #[]=(start, length) ⇒ Object? #[]=(range) ⇒ Object?
Element Assignment --- Sets the element at index
, or replaces a subarray from the start
index for length
elements, or replaces a subarray specified by the range
of indices.
If indices are greater than the current capacity of the array, the array grows automatically. Elements are inserted into the array at start
if length
is zero.
Negative indices will count backward from the end of the array. For start
and range
cases the starting index is just before an element.
An IndexError is raised if a negative index points past the beginning of the array.
See also Array#push, and Array#unshift.
a = Array.new
a[4] = "4"; #=> [nil, nil, nil, nil, "4"]
a[0, 3] = [ 'a', 'b', 'c' ] #=> ["a", "b", "c", nil, "4"]
a[1..2] = [ 1, 2 ] #=> ["a", 1, 2, nil, "4"]
a[0, 2] = "?" #=> ["?", 2, nil, "4"]
a[0..2] = "A" #=> ["A", "4"]
a[-1] = "Z" #=> ["A", "Z"]
a[1..-1] = nil #=> ["A", nil]
a[1..-1] = [] #=> ["A"]
a[0, 0] = [ 1, 2 ] #=> [1, 2, "A"]
a[3, 0] = "B" #=> [1, 2, "A", "B"]
1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 |
# File 'array.c', line 1586
static VALUE
rb_ary_aset(int argc, VALUE *argv, VALUE ary)
{
long offset, beg, len;
if (argc == 3) {
rb_ary_modify_check(ary);
beg = NUM2LONG(argv[0]);
len = NUM2LONG(argv[1]);
rb_ary_splice(ary, beg, len, argv[2]);
return argv[2];
}
rb_check_arity(argc, 2, 2);
rb_ary_modify_check(ary);
if (FIXNUM_P(argv[0])) {
offset = FIX2LONG(argv[0]);
goto fixnum;
}
if (rb_range_beg_len(argv[0], &beg, &len, RARRAY_LEN(ary), 1)) {
/* check if idx is Range */
rb_ary_splice(ary, beg, len, argv[1]);
return argv[1];
}
offset = NUM2LONG(argv[0]);
fixnum:
rb_ary_store(ary, offset, argv[1]);
return argv[1];
}
|
#assoc(obj) ⇒ nil
Searches through an array whose elements are also arrays comparing obj
with the first element of each contained array using obj.==
.
Returns the first contained array that matches (that is, the first associated array), or nil
if no match is found.
See also Array#rassoc
s1 = [ "colors", "red", "blue", "green" ]
s2 = [ "letters", "a", "b", "c" ]
s3 = "foo"
a = [ s1, s2, s3 ]
a.assoc("letters") #=> [ "letters", "a", "b", "c" ]
a.assoc("foo") #=> nil
3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 |
# File 'array.c', line 3477
VALUE
rb_ary_assoc(VALUE ary, VALUE key)
{
long i;
VALUE v;
for (i = 0; i < RARRAY_LEN(ary); ++i) {
v = rb_check_array_type(RARRAY_PTR(ary)[i]);
if (!NIL_P(v) && RARRAY_LEN(v) > 0 &&
rb_equal(RARRAY_PTR(v)[0], key))
return v;
}
return Qnil;
}
|
#at(index) ⇒ Object?
Returns the element at index
. A negative index counts from the end of self
. Returns nil
if the index is out of range. See also Array#[].
a = [ "a", "b", "c", "d", "e" ]
a.at(0) #=> "a"
a.at(-1) #=> "e"
1210 1211 1212 1213 1214 |
# File 'array.c', line 1210
static VALUE
rb_ary_at(VALUE ary, VALUE pos)
{
return rb_ary_entry(ary, NUM2LONG(pos));
}
|
#bsearch {|x| ... } ⇒ Object
By using binary search, finds a value from this array which meets the given condition in O(log n) where n is the size of the array.
You can use this method in two use cases: a find-minimum mode and a find-any mode. In either case, the elements of the array must be monotone (or sorted) with respect to the block.
In find-minimum mode (this is a good choice for typical use case), the block must return true or false, and there must be an index i (0 <= i <= ary.size) so that:
-
the block returns false for any element whose index is less than i, and
-
the block returns true for any element whose index is greater than or equal to i.
This method returns the i-th element. If i is equal to ary.size, it returns nil.
ary = [0, 4, 7, 10, 12]
ary.bsearch {|x| x >= 4 } #=> 4
ary.bsearch {|x| x >= 6 } #=> 7
ary.bsearch {|x| x >= -1 } #=> 0
ary.bsearch {|x| x >= 100 } #=> nil
In find-any mode (this behaves like libc's bsearch(3)), the block must return a number, and there must be two indices i and j (0 <= i <= j <= ary.size) so that:
-
the block returns a positive number for ary if 0 <= k < i,
-
the block returns zero for ary if i <= k < j, and
-
the block returns a negative number for ary if j <= k < ary.size.
Under this condition, this method returns any element whose index is within i...j. If i is equal to j (i.e., there is no element that satisfies the block), this method returns nil.
ary = [0, 4, 7, 10, 12]
# try to find v such that 4 <= v < 8
ary.bsearch {|x| 1 - x / 4 } #=> 4 or 7
# try to find v such that 8 <= v < 10
ary.bsearch {|x| 4 - x / 2 } #=> nil
You must not mix the two modes at a time; the block must always return either true/false, or always return a number. It is undefined which value is actually picked up at each iteration.
2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 |
# File 'array.c', line 2434
static VALUE
rb_ary_bsearch(VALUE ary)
{
long low = 0, high = RARRAY_LEN(ary), mid;
int smaller = 0, satisfied = 0;
VALUE v, val;
RETURN_ENUMERATOR(ary, 0, 0);
while (low < high) {
mid = low + ((high - low) / 2);
val = rb_ary_entry(ary, mid);
v = rb_yield(val);
if (FIXNUM_P(v)) {
if (FIX2INT(v) == 0) return val;
smaller = FIX2INT(v) < 0;
}
else if (v == Qtrue) {
satisfied = 1;
smaller = 1;
}
else if (v == Qfalse || v == Qnil) {
smaller = 0;
}
else if (rb_obj_is_kind_of(v, rb_cNumeric)) {
switch (rb_cmpint(rb_funcall(v, id_cmp, 1, INT2FIX(0)), v, INT2FIX(0))) {
case 0: return val;
case 1: smaller = 1; break;
case -1: smaller = 0;
}
}
else {
rb_raise(rb_eTypeError, "wrong argument type %s"
" (must be numeric, true, false or nil)",
rb_obj_classname(v));
}
if (smaller) {
high = mid;
}
else {
low = mid + 1;
}
}
if (low == RARRAY_LEN(ary)) return Qnil;
if (!satisfied) return Qnil;
return rb_ary_entry(ary, low);
}
|
#clear ⇒ Object
Removes all elements from self
.
a = [ "a", "b", "c", "d", "e" ]
a.clear #=> [ ]
3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 |
# File 'array.c', line 3220
VALUE
rb_ary_clear(VALUE ary)
{
rb_ary_modify_check(ary);
ARY_SET_LEN(ary, 0);
if (ARY_SHARED_P(ary)) {
if (!ARY_EMBED_P(ary)) {
rb_ary_unshare(ary);
FL_SET_EMBED(ary);
}
}
else if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
ary_resize_capa(ary, ARY_DEFAULT_SIZE * 2);
}
return ary;
}
|
#collect {|item| ... } ⇒ Object #map {|item| ... } ⇒ Object #collect ⇒ Enumerator #map ⇒ Enumerator
Invokes the given block once for each element of self
.
Creates a new array containing the values returned by the block.
See also Enumerable#collect.
If no block is given, an Enumerator is returned instead.
a = [ "a", "b", "c", "d" ]
a.map { |x| x + "!" } #=> ["a!", "b!", "c!", "d!"]
a #=> ["a", "b", "c", "d"]
2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 |
# File 'array.c', line 2533
static VALUE
rb_ary_collect(VALUE ary)
{
long i;
VALUE collect;
RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
collect = rb_ary_new2(RARRAY_LEN(ary));
for (i = 0; i < RARRAY_LEN(ary); i++) {
rb_ary_push(collect, rb_yield(RARRAY_PTR(ary)[i]));
}
return collect;
}
|
#collect! {|item| ... } ⇒ Object #map! {|item| ... } ⇒ Object #collect! ⇒ Enumerator #map! ⇒ Enumerator
Invokes the given block once for each element of self
, replacing the element with the value returned by the block.
See also Enumerable#collect.
If no block is given, an Enumerator is returned instead.
a = [ "a", "b", "c", "d" ]
a.map! {|x| x + "!" }
a #=> [ "a!", "b!", "c!", "d!" ]
2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 |
# File 'array.c', line 2567
static VALUE
rb_ary_collect_bang(VALUE ary)
{
long i;
RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
rb_ary_modify(ary);
for (i = 0; i < RARRAY_LEN(ary); i++) {
rb_ary_store(ary, i, rb_yield(RARRAY_PTR(ary)[i]));
}
return ary;
}
|
#combination(n) {|c| ... } ⇒ Object #combination(n) ⇒ Enumerator
When invoked with a block, yields all combinations of length n
of elements from the array and then returns the array itself.
The implementation makes no guarantees about the order in which the combinations are yielded.
If no block is given, an Enumerator is returned instead.
Examples:
a = [1, 2, 3, 4]
a.combination(1).to_a #=> [[1],[2],[3],[4]]
a.combination(2).to_a #=> [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
a.combination(3).to_a #=> [[1,2,3],[1,2,4],[1,3,4],[2,3,4]]
a.combination(4).to_a #=> [[1,2,3,4]]
a.combination(0).to_a #=> [[]] # one combination of length 0
a.combination(5).to_a #=> [] # no combinations of length 5
4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 |
# File 'array.c', line 4723
static VALUE
rb_ary_combination(VALUE ary, VALUE num)
{
long n, i, len;
n = NUM2LONG(num);
RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_combination_size);
len = RARRAY_LEN(ary);
if (n < 0 || len < n) {
/* yield nothing */
}
else if (n == 0) {
rb_yield(rb_ary_new2(0));
}
else if (n == 1) {
for (i = 0; i < len; i++) {
rb_yield(rb_ary_new3(1, RARRAY_PTR(ary)[i]));
}
}
else {
volatile VALUE t0 = tmpbuf(n+1, sizeof(long));
long *stack = (long*)RSTRING_PTR(t0);
volatile VALUE cc = tmpary(n);
VALUE *chosen = RARRAY_PTR(cc);
long lev = 0;
MEMZERO(stack, long, n);
stack[0] = -1;
for (;;) {
chosen[lev] = RARRAY_PTR(ary)[stack[lev+1]];
for (lev++; lev < n; lev++) {
chosen[lev] = RARRAY_PTR(ary)[stack[lev+1] = stack[lev]+1];
}
rb_yield(rb_ary_new4(n, chosen));
if (RBASIC(t0)->klass) {
rb_raise(rb_eRuntimeError, "combination reentered");
}
do {
if (lev == 0) goto done;
stack[lev--]++;
} while (stack[lev+1]+n == len+lev+1);
}
done:
tmpbuf_discard(t0);
tmpary_discard(cc);
}
return ary;
}
|
#compact ⇒ Object
Returns a copy of self
with all nil
elements removed.
[ "a", nil, "b", nil, "c", nil ].compact
#=> [ "a", "b", "c" ]
4081 4082 4083 4084 4085 4086 4087 |
# File 'array.c', line 4081
static VALUE
rb_ary_compact(VALUE ary)
{
ary = rb_ary_dup(ary);
rb_ary_compact_bang(ary);
return ary;
}
|
#compact! ⇒ nil
Removes nil
elements from the array.
Returns nil
if no changes were made, otherwise returns the array.
[ "a", nil, "b", nil, "c" ].compact! #=> [ "a", "b", "c" ]
[ "a", "b", "c" ].compact! #=> nil
4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 |
# File 'array.c', line 4045
static VALUE
rb_ary_compact_bang(VALUE ary)
{
VALUE *p, *t, *end;
long n;
rb_ary_modify(ary);
p = t = RARRAY_PTR(ary);
end = p + RARRAY_LEN(ary);
while (t < end) {
if (NIL_P(*t)) t++;
else *p++ = *t++;
}
n = p - RARRAY_PTR(ary);
if (RARRAY_LEN(ary) == n) {
return Qnil;
}
ARY_SET_LEN(ary, n);
if (n * 2 < ARY_CAPA(ary) && ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
ary_resize_capa(ary, n * 2);
}
return ary;
}
|
#concat(other_ary) ⇒ Object
Appends the elements of other_ary
to self
.
[ "a", "b" ].concat( ["c", "d"] ) #=> [ "a", "b", "c", "d" ]
a = [ 1, 2, 3 ]
a.concat( [ 4, 5 ] )
a #=> [ 1, 2, 3, 4, 5 ]
See also Array#+.
3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 |
# File 'array.c', line 3382
VALUE
rb_ary_concat(VALUE x, VALUE y)
{
rb_ary_modify_check(x);
y = to_ary(y);
if (RARRAY_LEN(y) > 0) {
rb_ary_splice(x, RARRAY_LEN(x), 0, y);
}
return x;
}
|
#count ⇒ Integer #count(obj) ⇒ Integer #count {|item| ... } ⇒ Integer
Returns the number of elements.
If an argument is given, counts the number of elements which equal obj
using ===
.
If a block is given, counts the number of elements for which the block returns a true value.
ary = [1, 2, 4, 2]
ary.count #=> 4
ary.count(2) #=> 2
ary.count { |x| x%2 == 0 } #=> 3
4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 |
# File 'array.c', line 4110
static VALUE
rb_ary_count(int argc, VALUE *argv, VALUE ary)
{
long n = 0;
if (argc == 0) {
VALUE *p, *pend;
if (!rb_block_given_p())
return LONG2NUM(RARRAY_LEN(ary));
for (p = RARRAY_PTR(ary), pend = p + RARRAY_LEN(ary); p < pend; p++) {
if (RTEST(rb_yield(*p))) n++;
}
}
else {
VALUE obj, *p, *pend;
rb_scan_args(argc, argv, "1", &obj);
if (rb_block_given_p()) {
rb_warn("given block not used");
}
for (p = RARRAY_PTR(ary), pend = p + RARRAY_LEN(ary); p < pend; p++) {
if (rb_equal(*p, obj)) n++;
}
}
return LONG2NUM(n);
}
|
#cycle(n = nil) {|obj| ... } ⇒ nil #cycle(n = nil) ⇒ Enumerator
Calls the given block for each element n
times or forever if nil
is given.
Does nothing if a non-positive number is given or the array is empty.
Returns nil
if the loop has finished without getting interrupted.
If no block is given, an Enumerator is returned instead.
a = ["a", "b", "c"]
a.cycle { |x| puts x } # print, a, b, c, a, b, c,.. forever.
a.cycle(2) { |x| puts x } # print, a, b, c, a, b, c.
4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 |
# File 'array.c', line 4510
static VALUE
rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
{
long n, i;
VALUE nv = Qnil;
rb_scan_args(argc, argv, "01", &nv);
RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_cycle_size);
if (NIL_P(nv)) {
n = -1;
}
else {
n = NUM2LONG(nv);
if (n <= 0) return Qnil;
}
while (RARRAY_LEN(ary) > 0 && (n < 0 || 0 < n--)) {
for (i=0; i<RARRAY_LEN(ary); i++) {
rb_yield(RARRAY_PTR(ary)[i]);
}
}
return Qnil;
}
|
#delete(obj) ⇒ nil #delete(obj) { ... } ⇒ Object
Deletes all items from self
that are equal to obj
.
Returns the last deleted item, or nil
if no matching item is found.
If the optional code block is given, the result of the block is returned if the item is not found. (To remove nil
elements and get an informative return value, use Array#compact!)
a = [ "a", "b", "b", "b", "c" ]
a.delete("b") #=> "b"
a #=> ["a", "c"]
a.delete("z") #=> nil
a.delete("z") { "not found" } #=> "not found"
2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 |
# File 'array.c', line 2760
VALUE
rb_ary_delete(VALUE ary, VALUE item)
{
VALUE v = item;
long i1, i2;
for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
VALUE e = RARRAY_PTR(ary)[i1];
if (rb_equal(e, item)) {
v = e;
continue;
}
if (i1 != i2) {
rb_ary_store(ary, i2, e);
}
i2++;
}
if (RARRAY_LEN(ary) == i2) {
if (rb_block_given_p()) {
return rb_yield(item);
}
return Qnil;
}
ary_resize_smaller(ary, i2);
return v;
}
|
#delete_at(index) ⇒ Object?
Deletes the element at the specified index
, returning that element, or nil
if the index
is out of range.
See also Array#slice!
a = ["ant", "bat", "cat", "dog"]
a.delete_at(2) #=> "cat"
a #=> ["ant", "bat", "dog"]
a.delete_at(99) #=> nil
2849 2850 2851 2852 2853 |
# File 'array.c', line 2849
static VALUE
rb_ary_delete_at_m(VALUE ary, VALUE pos)
{
return rb_ary_delete_at(ary, NUM2LONG(pos));
}
|
#delete_if {|item| ... } ⇒ Object #delete_if ⇒ Enumerator
Deletes every element of self
for which block evaluates to true
.
The array is changed instantly every time the block is called, not after the iteration is over.
See also Array#reject!
If no block is given, an Enumerator is returned instead.
a = [ "a", "b", "c" ]
a.delete_if {|x| x >= "b" } #=> ["a"]
3026 3027 3028 3029 3030 3031 3032 |
# File 'array.c', line 3026
static VALUE
rb_ary_delete_if(VALUE ary)
{
RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
ary_reject_bang(ary);
return ary;
}
|
#drop(n) ⇒ Object
Drops first n
elements from ary
and returns the rest of the elements in an array.
If a negative number is given, raises an ArgumentError.
See also Array#take
a = [1, 2, 3, 4, 5, 0]
a.drop(3) #=> [4, 5, 0]
5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 |
# File 'array.c', line 5159
static VALUE
rb_ary_drop(VALUE ary, VALUE n)
{
VALUE result;
long pos = NUM2LONG(n);
if (pos < 0) {
rb_raise(rb_eArgError, "attempt to drop negative size");
}
result = rb_ary_subseq(ary, pos, RARRAY_LEN(ary));
if (result == Qnil) result = rb_ary_new();
return result;
}
|
#drop_while {|arr| ... } ⇒ Object #drop_while ⇒ Enumerator
Drops elements up to, but not including, the first element for which the block returns nil
or false
and returns an array containing the remaining elements.
If no block is given, an Enumerator is returned instead.
See also Array#take_while
a = [1, 2, 3, 4, 5, 0]
a.drop_while {|i| i < 3 } #=> [3, 4, 5, 0]
5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 |
# File 'array.c', line 5191
static VALUE
rb_ary_drop_while(VALUE ary)
{
long i;
RETURN_ENUMERATOR(ary, 0, 0);
for (i = 0; i < RARRAY_LEN(ary); i++) {
if (!RTEST(rb_yield(RARRAY_PTR(ary)[i]))) break;
}
return rb_ary_drop(ary, LONG2FIX(i));
}
|
#each {|item| ... } ⇒ Object #each ⇒ Enumerator
Calls the given block once for each element in self
, passing that element as a parameter.
An Enumerator is returned if no block is given.
a = [ "a", "b", "c" ]
a.each {|x| print x, " -- " }
produces:
a -- b -- c --
1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 |
# File 'array.c', line 1670
VALUE
rb_ary_each(VALUE array)
{
long i;
volatile VALUE ary = array;
RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
for (i=0; i<RARRAY_LEN(ary); i++) {
rb_yield(RARRAY_PTR(ary)[i]);
}
return ary;
}
|
#each_index {|index| ... } ⇒ Object #each_index ⇒ Enumerator
Same as Array#each, but passes the index
of the element instead of the element itself.
An Enumerator is returned if no block is given.
a = [ "a", "b", "c" ]
a.each_index {|x| print x, " -- " }
produces:
0 -- 1 -- 2 --
1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 |
# File 'array.c', line 1701
static VALUE
rb_ary_each_index(VALUE ary)
{
long i;
RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
for (i=0; i<RARRAY_LEN(ary); i++) {
rb_yield(LONG2NUM(i));
}
return ary;
}
|
#empty? ⇒ Boolean
Returns true
if self
contains no elements.
[].empty? #=> true
1770 1771 1772 1773 1774 1775 1776 |
# File 'array.c', line 1770
static VALUE
rb_ary_empty_p(VALUE ary)
{
if (RARRAY_LEN(ary) == 0)
return Qtrue;
return Qfalse;
}
|
#eql?(other) ⇒ Boolean
Returns true
if self
and other
are the same object, or are both arrays with the same content.
3608 3609 3610 3611 3612 3613 3614 3615 |
# File 'array.c', line 3608
static VALUE
rb_ary_eql(VALUE ary1, VALUE ary2)
{
if (ary1 == ary2) return Qtrue;
if (!RB_TYPE_P(ary2, T_ARRAY)) return Qfalse;
if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2);
}
|
#fetch(index) ⇒ Object #fetch(index, default) ⇒ Object #fetch(index) {|index| ... } ⇒ Object
Tries to return the element at position index
, but throws an IndexError exception if the referenced index
lies outside of the array bounds. This error can be prevented by supplying a second argument, which will act as a default
value.
Alternatively, if a block is given it will only be executed when an invalid index
is referenced. Negative values of index
count from the end of the array.
a = [ 11, 22, 33, 44 ]
a.fetch(1) #=> 22
a.fetch(-1) #=> 44
a.fetch(4, 'cat') #=> "cat"
a.fetch(100) { |i| puts "#{i} is out of bounds" }
#=> "100 is out of bounds"
1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 |
# File 'array.c', line 1293
static VALUE
rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
{
VALUE pos, ifnone;
long block_given;
long idx;
rb_scan_args(argc, argv, "11", &pos, &ifnone);
block_given = rb_block_given_p();
if (block_given && argc == 2) {
rb_warn("block supersedes default value argument");
}
idx = NUM2LONG(pos);
if (idx < 0) {
idx += RARRAY_LEN(ary);
}
if (idx < 0 || RARRAY_LEN(ary) <= idx) {
if (block_given) return rb_yield(pos);
if (argc == 1) {
rb_raise(rb_eIndexError, "index %ld outside of array bounds: %ld...%ld",
idx - (idx < 0 ? RARRAY_LEN(ary) : 0), -RARRAY_LEN(ary), RARRAY_LEN(ary));
}
return ifnone;
}
return RARRAY_PTR(ary)[idx];
}
|
#fill(obj) ⇒ Object #fill(obj, start[, length]) ⇒ Object #fill(obj, range) ⇒ Object #fill {|index| ... } ⇒ Object #fill(start[, length]) {|index| ... } ⇒ Object #fill(range) {|index| ... } ⇒ Object
The first three forms set the selected elements of self
(which may be the entire array) to obj
.
A start
of nil
is equivalent to zero.
A length
of nil
is equivalent to the length of the array.
The last three forms fill the array with the value of the given block, which is passed the absolute index of each element to be filled.
Negative values of start
count from the end of the array, where -1
is the last element.
a = [ "a", "b", "c", "d" ]
a.fill("x") #=> ["x", "x", "x", "x"]
a.fill("z", 2, 2) #=> ["x", "x", "z", "z"]
a.fill("y", 0..1) #=> ["y", "y", "z", "z"]
a.fill { |i| i*i } #=> [0, 1, 4, 9]
a.fill(-2) { |i| i*i*i } #=> [0, 1, 8, 27]
3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 |
# File 'array.c', line 3267
static VALUE
rb_ary_fill(int argc, VALUE *argv, VALUE ary)
{
VALUE item, arg1, arg2;
long beg = 0, end = 0, len = 0;
VALUE *p, *pend;
int block_p = FALSE;
if (rb_block_given_p()) {
block_p = TRUE;
rb_scan_args(argc, argv, "02", &arg1, &arg2);
argc += 1; /* hackish */
}
else {
rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
}
switch (argc) {
case 1:
beg = 0;
len = RARRAY_LEN(ary);
break;
case 2:
if (rb_range_beg_len(arg1, &beg, &len, RARRAY_LEN(ary), 1)) {
break;
}
/* fall through */
case 3:
beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
if (beg < 0) {
beg = RARRAY_LEN(ary) + beg;
if (beg < 0) beg = 0;
}
len = NIL_P(arg2) ? RARRAY_LEN(ary) - beg : NUM2LONG(arg2);
break;
}
rb_ary_modify(ary);
if (len < 0) {
return ary;
}
if (beg >= ARY_MAX_SIZE || len > ARY_MAX_SIZE - beg) {
rb_raise(rb_eArgError, "argument too big");
}
end = beg + len;
if (RARRAY_LEN(ary) < end) {
if (end >= ARY_CAPA(ary)) {
ary_resize_capa(ary, end);
}
rb_mem_clear(RARRAY_PTR(ary) + RARRAY_LEN(ary), end - RARRAY_LEN(ary));
ARY_SET_LEN(ary, end);
}
if (block_p) {
VALUE v;
long i;
for (i=beg; i<end; i++) {
v = rb_yield(LONG2NUM(i));
if (i>=RARRAY_LEN(ary)) break;
RARRAY_PTR(ary)[i] = v;
}
}
else {
p = RARRAY_PTR(ary) + beg;
pend = p + len;
while (p < pend) {
*p++ = item;
}
}
return ary;
}
|
#index(obj) ⇒ Integer? #index {|item| ... } ⇒ Integer? #index ⇒ Enumerator
Returns the index of the first object in ary
such that the object is ==
to obj
.
If a block is given instead of an argument, returns the index of the first object for which the block returns true
. Returns nil
if no match is found.
See also Array#rindex.
An Enumerator is returned if neither a block nor argument is given.
a = [ "a", "b", "c" ]
a.index("b") #=> 1
a.index("z") #=> nil
a.index { |x| x == "b" } #=> 1
This is an alias of Array#find_index.
1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 |
# File 'array.c', line 1346
static VALUE
rb_ary_index(int argc, VALUE *argv, VALUE ary)
{
VALUE val;
long i;
if (argc == 0) {
RETURN_ENUMERATOR(ary, 0, 0);
for (i=0; i<RARRAY_LEN(ary); i++) {
if (RTEST(rb_yield(RARRAY_PTR(ary)[i]))) {
return LONG2NUM(i);
}
}
return Qnil;
}
rb_scan_args(argc, argv, "1", &val);
if (rb_block_given_p())
rb_warn("given block not used");
for (i=0; i<RARRAY_LEN(ary); i++) {
if (rb_equal(RARRAY_PTR(ary)[i], val))
return LONG2NUM(i);
}
return Qnil;
}
|
#first ⇒ Object? #first(n) ⇒ Object
Returns the first element, or the first n
elements, of the array. If the array is empty, the first form returns nil
, and the second form returns an empty array. See also Array#last for the opposite effect.
a = [ "q", "r", "s", "t" ]
a.first #=> "q"
a.first(2) #=> ["q", "r"]
1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 |
# File 'array.c', line 1231
static VALUE
rb_ary_first(int argc, VALUE *argv, VALUE ary)
{
if (argc == 0) {
if (RARRAY_LEN(ary) == 0) return Qnil;
return RARRAY_PTR(ary)[0];
}
else {
return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
}
}
|
#flatten ⇒ Object #flatten(level) ⇒ Object
Returns a new array that is a one-dimensional flattening of self
(recursively).
That is, for every element that is an array, extract its elements into the new array.
The optional level
argument determines the level of recursion to flatten.
s = [ 1, 2, 3 ] #=> [1, 2, 3]
t = [ 4, 5, 6, [7, 8] ] #=> [4, 5, 6, [7, 8]]
a = [ s, t, 9, 10 ] #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10]
a.flatten #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
a = [ 1, 2, [3, [4, 5] ] ]
a.flatten(1) #=> [1, 2, 3, [4, 5]]
4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 |
# File 'array.c', line 4259
static VALUE
rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
{
int mod = 0, level = -1;
VALUE result, lv;
rb_scan_args(argc, argv, "01", &lv);
if (!NIL_P(lv)) level = NUM2INT(lv);
if (level == 0) return ary_make_shared_copy(ary);
result = flatten(ary, level, &mod);
OBJ_INFECT(result, ary);
return result;
}
|
#flatten! ⇒ nil #flatten!(level) ⇒ nil
Flattens self
in place.
Returns nil
if no modifications were made (i.e., the array contains no subarrays.)
The optional level
argument determines the level of recursion to flatten.
a = [ 1, 2, [3, [4, 5] ] ]
a.flatten! #=> [1, 2, 3, 4, 5]
a.flatten! #=> nil
a #=> [1, 2, 3, 4, 5]
a = [ 1, 2, [3, [4, 5] ] ]
a.flatten!(1) #=> [1, 2, 3, [4, 5]]
4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 |
# File 'array.c', line 4214
static VALUE
rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
{
int mod = 0, level = -1;
VALUE result, lv;
rb_scan_args(argc, argv, "01", &lv);
rb_ary_modify_check(ary);
if (!NIL_P(lv)) level = NUM2INT(lv);
if (level == 0) return Qnil;
result = flatten(ary, level, &mod);
if (mod == 0) {
ary_discard(result);
return Qnil;
}
if (!(mod = ARY_EMBED_P(result))) rb_obj_freeze(result);
rb_ary_replace(ary, result);
if (mod) ARY_SET_EMBED_LEN(result, 0);
return ary;
}
|
#frozen? ⇒ Boolean
Return true
if this array is frozen (or temporarily frozen while being sorted). See also Object#frozen?
344 345 346 347 348 349 |
# File 'array.c', line 344
static VALUE
rb_ary_frozen_p(VALUE ary)
{
if (OBJ_FROZEN(ary)) return Qtrue;
return Qfalse;
}
|
#hash ⇒ Fixnum
Compute a hash-code for this array.
Two arrays with the same content will have the same hash code (and will compare using #eql?).
3648 3649 3650 3651 3652 |
# File 'array.c', line 3648
static VALUE
rb_ary_hash(VALUE ary)
{
return rb_exec_recursive_outer(recursive_hash, ary, 0);
}
|
#include?(object) ⇒ Boolean
Returns true
if the given object
is present in self
(that is, if any object ==
object
), otherwise returns false
.
a = [ "a", "b", "c" ]
a.include?("b") #=> true
a.include?("z") #=> false
3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 |
# File 'array.c', line 3666
VALUE
rb_ary_includes(VALUE ary, VALUE item)
{
long i;
for (i=0; i<RARRAY_LEN(ary); i++) {
if (rb_equal(RARRAY_PTR(ary)[i], item)) {
return Qtrue;
}
}
return Qfalse;
}
|
#index(obj) ⇒ Integer? #index {|item| ... } ⇒ Integer? #index ⇒ Enumerator
Returns the index of the first object in ary
such that the object is ==
to obj
.
If a block is given instead of an argument, returns the index of the first object for which the block returns true
. Returns nil
if no match is found.
See also Array#rindex.
An Enumerator is returned if neither a block nor argument is given.
a = [ "a", "b", "c" ]
a.index("b") #=> 1
a.index("z") #=> nil
a.index { |x| x == "b" } #=> 1
This is an alias of Array#find_index.
1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 |
# File 'array.c', line 1346
static VALUE
rb_ary_index(int argc, VALUE *argv, VALUE ary)
{
VALUE val;
long i;
if (argc == 0) {
RETURN_ENUMERATOR(ary, 0, 0);
for (i=0; i<RARRAY_LEN(ary); i++) {
if (RTEST(rb_yield(RARRAY_PTR(ary)[i]))) {
return LONG2NUM(i);
}
}
return Qnil;
}
rb_scan_args(argc, argv, "1", &val);
if (rb_block_given_p())
rb_warn("given block not used");
for (i=0; i<RARRAY_LEN(ary); i++) {
if (rb_equal(RARRAY_PTR(ary)[i], val))
return LONG2NUM(i);
}
return Qnil;
}
|
#replace(other_ary) ⇒ Object
Replaces the contents of self
with the contents of other_ary
, truncating or expanding if necessary.
a = [ "a", "b", "c", "d", "e" ]
a.replace([ "x", "y", "z" ]) #=> ["x", "y", "z"]
a #=> ["x", "y", "z"]
3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 |
# File 'array.c', line 3168
VALUE
rb_ary_replace(VALUE copy, VALUE orig)
{
rb_ary_modify_check(copy);
orig = to_ary(orig);
if (copy == orig) return copy;
if (RARRAY_LEN(orig) <= RARRAY_EMBED_LEN_MAX) {
VALUE *ptr;
VALUE shared = 0;
if (ARY_OWNS_HEAP_P(copy)) {
xfree(RARRAY_PTR(copy));
}
else if (ARY_SHARED_P(copy)) {
shared = ARY_SHARED(copy);
FL_UNSET_SHARED(copy);
}
FL_SET_EMBED(copy);
ptr = RARRAY_PTR(orig);
MEMCPY(RARRAY_PTR(copy), ptr, VALUE, RARRAY_LEN(orig));
if (shared) {
rb_ary_decrement_share(shared);
}
ARY_SET_LEN(copy, RARRAY_LEN(orig));
}
else {
VALUE shared = ary_make_shared(orig);
if (ARY_OWNS_HEAP_P(copy)) {
xfree(RARRAY_PTR(copy));
}
else {
rb_ary_unshare_safe(copy);
}
FL_UNSET_EMBED(copy);
ARY_SET_PTR(copy, RARRAY_PTR(orig));
ARY_SET_LEN(copy, RARRAY_LEN(orig));
rb_ary_set_shared(copy, shared);
}
return copy;
}
|
#insert(index, obj...) ⇒ Object
Inserts the given values before the element with the given index
.
Negative indices count backwards from the end of the array, where -1
is the last element.
a = %w{ a b c d }
a.insert(2, 99) #=> ["a", "b", 99, "c", "d"]
a.insert(-2, 1, 2, 3) #=> ["a", "b", 99, "c", 1, 2, 3, "d"]
1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 |
# File 'array.c', line 1630
static VALUE
rb_ary_insert(int argc, VALUE *argv, VALUE ary)
{
long pos;
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
rb_ary_modify_check(ary);
if (argc == 1) return ary;
pos = NUM2LONG(argv[0]);
if (pos == -1) {
pos = RARRAY_LEN(ary);
}
if (pos < 0) {
pos++;
}
rb_ary_splice(ary, pos, 0, rb_ary_new4(argc - 1, argv + 1));
return ary;
}
|
#inspect ⇒ String #to_s ⇒ String Also known as: to_s
Creates a string representation of self
.
[ "a", "b", "c" ].to_s #=> "[\"a\", \"b\", \"c\"]"
1987 1988 1989 1990 1991 1992 |
# File 'array.c', line 1987
static VALUE
rb_ary_inspect(VALUE ary)
{
if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new2("[]");
return rb_exec_recursive(inspect_ary, ary, 0);
}
|
#join(separator = $,) ⇒ String
Returns a string created by converting each element of the array to a string, separated by the given separator
. If the separator
is nil
, it uses current $,. If both the separator
and $, are nil, it uses empty string.
[ "a", "b", "c" ].join #=> "abc"
[ "a", "b", "c" ].join("-") #=> "a-b-c"
1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 |
# File 'array.c', line 1942
static VALUE
rb_ary_join_m(int argc, VALUE *argv, VALUE ary)
{
VALUE sep;
rb_scan_args(argc, argv, "01", &sep);
if (NIL_P(sep)) sep = rb_output_fs;
return rb_ary_join(ary, sep);
}
|
#keep_if {|item| ... } ⇒ Object #keep_if ⇒ Enumerator
Deletes every element of self
for which the given block evaluates to false
.
See also Array#select!
If no block is given, an Enumerator is returned instead.
a = %w{ a b c d e f }
a.keep_if { |v| v =~ /[aeiou]/ } #=> ["a", "e"]
2719 2720 2721 2722 2723 2724 2725 |
# File 'array.c', line 2719
static VALUE
rb_ary_keep_if(VALUE ary)
{
RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
rb_ary_select_bang(ary);
return ary;
}
|
#last ⇒ Object? #last(n) ⇒ Object
Returns the last element(s) of self
. If the array is empty, the first form returns nil
.
See also Array#first for the opposite effect.
a = [ "w", "x", "y", "z" ]
a.last #=> "z"
a.last(2) #=> ["y", "z"]
1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 |
# File 'array.c', line 1258
VALUE
rb_ary_last(int argc, VALUE *argv, VALUE ary)
{
if (argc == 0) {
if (RARRAY_LEN(ary) == 0) return Qnil;
return RARRAY_PTR(ary)[RARRAY_LEN(ary)-1];
}
else {
return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
}
}
|
#length ⇒ Integer Also known as: size
Returns the number of elements in self
. May be zero.
[ 1, 2, 3, 4, 5 ].length #=> 5
[].length #=> 0
1754 1755 1756 1757 1758 1759 |
# File 'array.c', line 1754
static VALUE
rb_ary_length(VALUE ary)
{
long len = RARRAY_LEN(ary);
return LONG2NUM(len);
}
|
#collect {|item| ... } ⇒ Object #map {|item| ... } ⇒ Object #collect ⇒ Enumerator #map ⇒ Enumerator
Invokes the given block once for each element of self
.
Creates a new array containing the values returned by the block.
See also Enumerable#collect.
If no block is given, an Enumerator is returned instead.
a = [ "a", "b", "c", "d" ]
a.map { |x| x + "!" } #=> ["a!", "b!", "c!", "d!"]
a #=> ["a", "b", "c", "d"]
2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 |
# File 'array.c', line 2533
static VALUE
rb_ary_collect(VALUE ary)
{
long i;
VALUE collect;
RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
collect = rb_ary_new2(RARRAY_LEN(ary));
for (i = 0; i < RARRAY_LEN(ary); i++) {
rb_ary_push(collect, rb_yield(RARRAY_PTR(ary)[i]));
}
return collect;
}
|
#collect! {|item| ... } ⇒ Object #map! {|item| ... } ⇒ Object #collect! ⇒ Enumerator #map! ⇒ Enumerator
Invokes the given block once for each element of self
, replacing the element with the value returned by the block.
See also Enumerable#collect.
If no block is given, an Enumerator is returned instead.
a = [ "a", "b", "c", "d" ]
a.map! {|x| x + "!" }
a #=> [ "a!", "b!", "c!", "d!" ]
2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 |
# File 'array.c', line 2567
static VALUE
rb_ary_collect_bang(VALUE ary)
{
long i;
RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
rb_ary_modify(ary);
for (i = 0; i < RARRAY_LEN(ary); i++) {
rb_ary_store(ary, i, rb_yield(RARRAY_PTR(ary)[i]));
}
return ary;
}
|
#pack ⇒ Object
Packs the contents of arr into a binary sequence according to the directives in aTemplateString (see the table below) Directives "A," "a," and "Z" may be followed by a count, which gives the width of the resulting field. The remaining directives also may take a count, indicating the number of array elements to convert. If the count is an asterisk ("*
"), all remaining array elements will be converted. Any of the directives "sSiIlL
" may be followed by an underscore ("_
") or exclamation mark ("!
") to use the underlying platform's native size for the specified type; otherwise, they use a platform-independent size. Spaces are ignored in the template string. See also String#unpack
.
a = [ "a", "b", "c" ]
n = [ 65, 66, 67 ]
a.pack("A3A3A3") #=> "a b c "
a.pack("a3a3a3") #=> "a\000\000b\000\000c\000\000"
n.pack("ccc") #=> "ABC"
Directives for pack
.
Integer | Array |
Directive | Element | Meaning
---------------------------------------------------------------------------
C | Integer | 8-bit unsigned (unsigned char)
S | Integer | 16-bit unsigned, native endian (uint16_t)
L | Integer | 32-bit unsigned, native endian (uint32_t)
Q | Integer | 64-bit unsigned, native endian (uint64_t)
| |
c | Integer | 8-bit signed (signed char)
s | Integer | 16-bit signed, native endian (int16_t)
l | Integer | 32-bit signed, native endian (int32_t)
q | Integer | 64-bit signed, native endian (int64_t)
| |
S_, S! | Integer | unsigned short, native endian
I, I_, I! | Integer | unsigned int, native endian
L_, L! | Integer | unsigned long, native endian
| |
s_, s! | Integer | signed short, native endian
i, i_, i! | Integer | signed int, native endian
l_, l! | Integer | signed long, native endian
| |
S> L> Q> | Integer | same as the directives without ">" except
s> l> q> | | big endian
S!> I!> | | (available since Ruby 1.9.3)
L!> | | "S>" is same as "n"
s!> i!> | | "L>" is same as "N"
l!> | |
| |
S< L< Q< | Integer | same as the directives without "<" except
s< l< q< | | little endian
S!< I!< | | (available since Ruby 1.9.3)
L!< | | "S<" is same as "v"
s!< i!< | | "L<" is same as "V"
l!< | |
| |
n | Integer | 16-bit unsigned, network (big-endian) byte order
N | Integer | 32-bit unsigned, network (big-endian) byte order
v | Integer | 16-bit unsigned, VAX (little-endian) byte order
V | Integer | 32-bit unsigned, VAX (little-endian) byte order
| |
U | Integer | UTF-8 character
w | Integer | BER-compressed integer
Float | |
Directive | | Meaning
---------------------------------------------------------------------------
D, d | Float | double-precision, native format
F, f | Float | single-precision, native format
E | Float | double-precision, little-endian byte order
e | Float | single-precision, little-endian byte order
G | Float | double-precision, network (big-endian) byte order
g | Float | single-precision, network (big-endian) byte order
String | |
Directive | | Meaning
---------------------------------------------------------------------------
A | String | arbitrary binary string (space padded, count is width)
a | String | arbitrary binary string (null padded, count is width)
Z | String | same as ``a'', except that null is added with *
B | String | bit string (MSB first)
b | String | bit string (LSB first)
H | String | hex string (high nibble first)
h | String | hex string (low nibble first)
u | String | UU-encoded string
M | String | quoted printable, MIME encoding (see RFC2045)
m | String | base64 encoded string (see RFC 2045, count is width)
| | (if count is 0, no line feed are added, see RFC 4648)
P | String | pointer to a structure (fixed-length string)
p | String | pointer to a null-terminated string
Misc. | |
Directive | | Meaning
---------------------------------------------------------------------------
@ | --- | moves to absolute position
X | --- | back up a byte
x | --- | null byte
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 |
# File 'pack.c', line 368
static VALUE
pack_pack(VALUE ary, VALUE fmt)
{
static const char nul10[] = "\0\0\0\0\0\0\0\0\0\0";
static const char spc10[] = " ";
const char *p, *pend;
VALUE res, from, associates = 0;
char type;
long items, len, idx, plen;
const char *ptr;
int enc_info = 1; /* 0 - BINARY, 1 - US-ASCII, 2 - UTF-8 */
#ifdef NATINT_PACK
int natint; /* native integer */
#endif
int integer_size, bigendian_p;
StringValue(fmt);
p = RSTRING_PTR(fmt);
pend = p + RSTRING_LEN(fmt);
res = rb_str_buf_new(0);
items = RARRAY_LEN(ary);
idx = 0;
#define TOO_FEW (rb_raise(rb_eArgError, toofew), 0)
#define THISFROM (items > 0 ? RARRAY_PTR(ary)[idx] : TOO_FEW)
#define NEXTFROM (items-- > 0 ? RARRAY_PTR(ary)[idx++] : TOO_FEW)
while (p < pend) {
int explicit_endian = 0;
if (RSTRING_PTR(fmt) + RSTRING_LEN(fmt) != pend) {
rb_raise(rb_eRuntimeError, "format string modified");
}
type = *p++; /* get data type */
#ifdef NATINT_PACK
natint = 0;
#endif
if (ISSPACE(type)) continue;
if (type == '#') {
while ((p < pend) && (*p != '\n')) {
p++;
}
continue;
}
{
static const char natstr[] = "sSiIlL";
static const char endstr[] = "sSiIlLqQ";
modifiers:
switch (*p) {
case '_':
case '!':
if (strchr(natstr, type)) {
#ifdef NATINT_PACK
natint = 1;
#endif
p++;
}
else {
rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, natstr);
}
goto modifiers;
case '<':
case '>':
if (!strchr(endstr, type)) {
rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, endstr);
}
if (explicit_endian) {
rb_raise(rb_eRangeError, "Can't use both '<' and '>'");
}
explicit_endian = *p++;
goto modifiers;
}
}
if (*p == '*') { /* set data length */
len = strchr("@Xxu", type) ? 0
: strchr("PMm", type) ? 1
: items;
p++;
}
else if (ISDIGIT(*p)) {
errno = 0;
len = STRTOUL(p, (char**)&p, 10);
if (errno) {
rb_raise(rb_eRangeError, "pack length too big");
}
}
else {
len = 1;
}
switch (type) {
case 'U':
/* if encoding is US-ASCII, upgrade to UTF-8 */
if (enc_info == 1) enc_info = 2;
break;
case 'm': case 'M': case 'u':
/* keep US-ASCII (do nothing) */
break;
default:
/* fall back to BINARY */
enc_info = 0;
break;
}
switch (type) {
case 'A': case 'a': case 'Z':
case 'B': case 'b':
case 'H': case 'h':
from = NEXTFROM;
if (NIL_P(from)) {
ptr = "";
plen = 0;
}
else {
StringValue(from);
ptr = RSTRING_PTR(from);
plen = RSTRING_LEN(from);
OBJ_INFECT(res, from);
}
if (p[-1] == '*')
len = plen;
switch (type) {
case 'a': /* arbitrary binary string (null padded) */
case 'A': /* arbitrary binary string (ASCII space padded) */
case 'Z': /* null terminated string */
if (plen >= len) {
rb_str_buf_cat(res, ptr, len);
if (p[-1] == '*' && type == 'Z')
rb_str_buf_cat(res, nul10, 1);
}
else {
rb_str_buf_cat(res, ptr, plen);
len -= plen;
while (len >= 10) {
rb_str_buf_cat(res, (type == 'A')?spc10:nul10, 10);
len -= 10;
}
rb_str_buf_cat(res, (type == 'A')?spc10:nul10, len);
}
break;
#define castchar(from) (char)((from) & 0xff)
case 'b': /* bit string (ascending) */
{
int byte = 0;
long i, j = 0;
if (len > plen) {
j = (len - plen + 1)/2;
len = plen;
}
for (i=0; i++ < len; ptr++) {
if (*ptr & 1)
byte |= 128;
if (i & 7)
byte >>= 1;
else {
char c = castchar(byte);
rb_str_buf_cat(res, &c, 1);
byte = 0;
}
}
if (len & 7) {
char c;
byte >>= 7 - (len & 7);
c = castchar(byte);
rb_str_buf_cat(res, &c, 1);
}
len = j;
goto grow;
}
break;
case 'B': /* bit string (descending) */
{
int byte = 0;
long i, j = 0;
if (len > plen) {
j = (len - plen + 1)/2;
len = plen;
}
for (i=0; i++ < len; ptr++) {
byte |= *ptr & 1;
if (i & 7)
byte <<= 1;
else {
char c = castchar(byte);
rb_str_buf_cat(res, &c, 1);
byte = 0;
}
}
if (len & 7) {
char c;
byte <<= 7 - (len & 7);
c = castchar(byte);
rb_str_buf_cat(res, &c, 1);
}
len = j;
goto grow;
}
break;
case 'h': /* hex string (low nibble first) */
{
int byte = 0;
long i, j = 0;
if (len > plen) {
j = (len + 1) / 2 - (plen + 1) / 2;
len = plen;
}
for (i=0; i++ < len; ptr++) {
if (ISALPHA(*ptr))
byte |= (((*ptr & 15) + 9) & 15) << 4;
else
byte |= (*ptr & 15) << 4;
if (i & 1)
byte >>= 4;
else {
char c = castchar(byte);
rb_str_buf_cat(res, &c, 1);
byte = 0;
}
}
if (len & 1) {
char c = castchar(byte);
rb_str_buf_cat(res, &c, 1);
}
len = j;
goto grow;
}
break;
case 'H': /* hex string (high nibble first) */
{
int byte = 0;
long i, j = 0;
if (len > plen) {
j = (len + 1) / 2 - (plen + 1) / 2;
len = plen;
}
for (i=0; i++ < len; ptr++) {
if (ISALPHA(*ptr))
byte |= ((*ptr & 15) + 9) & 15;
else
byte |= *ptr & 15;
if (i & 1)
byte <<= 4;
else {
char c = castchar(byte);
rb_str_buf_cat(res, &c, 1);
byte = 0;
}
}
if (len & 1) {
char c = castchar(byte);
rb_str_buf_cat(res, &c, 1);
}
len = j;
goto grow;
}
break;
}
break;
case 'c': /* signed char */
case 'C': /* unsigned char */
while (len-- > 0) {
char c;
from = NEXTFROM;
c = (char)num2i32(from);
rb_str_buf_cat(res, &c, sizeof(char));
}
break;
case 's': /* signed short */
integer_size = NATINT_LEN(short, 2);
bigendian_p = BIGENDIAN_P();
goto pack_integer;
case 'S': /* unsigned short */
integer_size = NATINT_LEN(short, 2);
bigendian_p = BIGENDIAN_P();
goto pack_integer;
case 'i': /* signed int */
integer_size = (int)sizeof(int);
bigendian_p = BIGENDIAN_P();
goto pack_integer;
case 'I': /* unsigned int */
integer_size = (int)sizeof(int);
bigendian_p = BIGENDIAN_P();
goto pack_integer;
case 'l': /* signed long */
integer_size = NATINT_LEN(long, 4);
bigendian_p = BIGENDIAN_P();
goto pack_integer;
case 'L': /* unsigned long */
integer_size = NATINT_LEN(long, 4);
bigendian_p = BIGENDIAN_P();
goto pack_integer;
case 'q': /* signed quad (64bit) int */
integer_size = 8;
bigendian_p = BIGENDIAN_P();
goto pack_integer;
case 'Q': /* unsigned quad (64bit) int */
integer_size = 8;
bigendian_p = BIGENDIAN_P();
goto pack_integer;
case 'n': /* unsigned short (network byte-order) */
integer_size = 2;
bigendian_p = 1;
goto pack_integer;
case 'N': /* unsigned long (network byte-order) */
integer_size = 4;
bigendian_p = 1;
goto pack_integer;
case 'v': /* unsigned short (VAX byte-order) */
integer_size = 2;
bigendian_p = 0;
goto pack_integer;
case 'V': /* unsigned long (VAX byte-order) */
integer_size = 4;
bigendian_p = 0;
goto pack_integer;
pack_integer:
if (explicit_endian) {
bigendian_p = explicit_endian == '>';
}
switch (integer_size) {
#if defined(HAVE_INT16_T) && !defined(FORCE_BIG_PACK)
case SIZEOF_INT16_T:
while (len-- > 0) {
union {
int16_t i;
char a[sizeof(int16_t)];
} v;
from = NEXTFROM;
v.i = (int16_t)num2i32(from);
if (bigendian_p != BIGENDIAN_P()) v.i = swap16(v.i);
rb_str_buf_cat(res, v.a, sizeof(int16_t));
}
break;
#endif
#if defined(HAVE_INT32_T) && !defined(FORCE_BIG_PACK)
case SIZEOF_INT32_T:
while (len-- > 0) {
union {
int32_t i;
char a[sizeof(int32_t)];
} v;
from = NEXTFROM;
v.i = (int32_t)num2i32(from);
if (bigendian_p != BIGENDIAN_P()) v.i = swap32(v.i);
rb_str_buf_cat(res, v.a, sizeof(int32_t));
}
break;
#endif
#if defined(HAVE_INT64_T) && SIZEOF_LONG == SIZEOF_INT64_T && !defined(FORCE_BIG_PACK)
case SIZEOF_INT64_T:
while (len-- > 0) {
union {
int64_t i;
char a[sizeof(int64_t)];
} v;
from = NEXTFROM;
v.i = num2i32(from); /* can return 64bit value if SIZEOF_LONG == SIZEOF_INT64_T */
if (bigendian_p != BIGENDIAN_P()) v.i = swap64(v.i);
rb_str_buf_cat(res, v.a, sizeof(int64_t));
}
break;
#endif
default:
if (integer_size > MAX_INTEGER_PACK_SIZE)
rb_bug("unexpected intger size for pack: %d", integer_size);
while (len-- > 0) {
union {
unsigned long i[(MAX_INTEGER_PACK_SIZE+SIZEOF_LONG-1)/SIZEOF_LONG];
char a[(MAX_INTEGER_PACK_SIZE+SIZEOF_LONG-1)/SIZEOF_LONG*SIZEOF_LONG];
} v;
int num_longs = (integer_size+SIZEOF_LONG-1)/SIZEOF_LONG;
int i;
from = NEXTFROM;
rb_big_pack(from, v.i, num_longs);
if (bigendian_p) {
for (i = 0; i < num_longs/2; i++) {
unsigned long t = v.i[i];
v.i[i] = v.i[num_longs-1-i];
v.i[num_longs-1-i] = t;
}
}
if (bigendian_p != BIGENDIAN_P()) {
for (i = 0; i < num_longs; i++)
v.i[i] = swapl(v.i[i]);
}
rb_str_buf_cat(res,
bigendian_p ?
v.a + sizeof(long)*num_longs - integer_size :
v.a,
integer_size);
}
break;
}
break;
case 'f': /* single precision float in native format */
case 'F': /* ditto */
while (len-- > 0) {
float f;
from = NEXTFROM;
f = (float)RFLOAT_VALUE(rb_to_float(from));
rb_str_buf_cat(res, (char*)&f, sizeof(float));
}
break;
case 'e': /* single precision float in VAX byte-order */
while (len-- > 0) {
float f;
FLOAT_CONVWITH(ftmp);
from = NEXTFROM;
f = (float)RFLOAT_VALUE(rb_to_float(from));
f = HTOVF(f,ftmp);
rb_str_buf_cat(res, (char*)&f, sizeof(float));
}
break;
case 'E': /* double precision float in VAX byte-order */
while (len-- > 0) {
double d;
DOUBLE_CONVWITH(dtmp);
from = NEXTFROM;
d = RFLOAT_VALUE(rb_to_float(from));
d = HTOVD(d,dtmp);
rb_str_buf_cat(res, (char*)&d, sizeof(double));
}
break;
case 'd': /* double precision float in native format */
case 'D': /* ditto */
while (len-- > 0) {
double d;
from = NEXTFROM;
d = RFLOAT_VALUE(rb_to_float(from));
rb_str_buf_cat(res, (char*)&d, sizeof(double));
}
break;
case 'g': /* single precision float in network byte-order */
while (len-- > 0) {
float f;
FLOAT_CONVWITH(ftmp);
from = NEXTFROM;
f = (float)RFLOAT_VALUE(rb_to_float(from));
f = HTONF(f,ftmp);
rb_str_buf_cat(res, (char*)&f, sizeof(float));
}
break;
case 'G': /* double precision float in network byte-order */
while (len-- > 0) {
double d;
DOUBLE_CONVWITH(dtmp);
from = NEXTFROM;
d = RFLOAT_VALUE(rb_to_float(from));
d = HTOND(d,dtmp);
rb_str_buf_cat(res, (char*)&d, sizeof(double));
}
break;
case 'x': /* null byte */
grow:
while (len >= 10) {
rb_str_buf_cat(res, nul10, 10);
len -= 10;
}
rb_str_buf_cat(res, nul10, len);
break;
case 'X': /* back up byte */
shrink:
plen = RSTRING_LEN(res);
if (plen < len)
rb_raise(rb_eArgError, "X outside of string");
rb_str_set_len(res, plen - len);
break;
case '@': /* null fill to absolute position */
len -= RSTRING_LEN(res);
if (len > 0) goto grow;
len = -len;
if (len > 0) goto shrink;
break;
case '%':
rb_raise(rb_eArgError, "%% is not supported");
break;
case 'U': /* Unicode character */
while (len-- > 0) {
SIGNED_VALUE l;
char buf[8];
int le;
from = NEXTFROM;
from = rb_to_int(from);
l = NUM2LONG(from);
if (l < 0) {
rb_raise(rb_eRangeError, "pack(U): value out of range");
}
le = rb_uv_to_utf8(buf, l);
rb_str_buf_cat(res, (char*)buf, le);
}
break;
case 'u': /* uuencoded string */
case 'm': /* base64 encoded string */
from = NEXTFROM;
StringValue(from);
ptr = RSTRING_PTR(from);
plen = RSTRING_LEN(from);
if (len == 0 && type == 'm') {
encodes(res, ptr, plen, type, 0);
ptr += plen;
break;
}
if (len <= 2)
len = 45;
else if (len > 63 && type == 'u')
len = 63;
else
len = len / 3 * 3;
while (plen > 0) {
long todo;
if (plen > len)
todo = len;
else
todo = plen;
encodes(res, ptr, todo, type, 1);
plen -= todo;
ptr += todo;
}
break;
case 'M': /* quoted-printable encoded string */
from = rb_obj_as_string(NEXTFROM);
if (len <= 1)
len = 72;
qpencode(res, from, len);
break;
case 'P': /* pointer to packed byte string */
from = THISFROM;
if (!NIL_P(from)) {
StringValue(from);
if (RSTRING_LEN(from) < len) {
rb_raise(rb_eArgError, "too short buffer for P(%ld for %ld)",
RSTRING_LEN(from), len);
}
}
len = 1;
/* FALL THROUGH */
case 'p': /* pointer to string */
while (len-- > 0) {
char *t;
from = NEXTFROM;
if (NIL_P(from)) {
t = 0;
}
else {
t = StringValuePtr(from);
}
if (!associates) {
associates = rb_ary_new();
}
rb_ary_push(associates, from);
rb_obj_taint(from);
rb_str_buf_cat(res, (char*)&t, sizeof(char*));
}
break;
case 'w': /* BER compressed integer */
while (len-- > 0) {
unsigned long ul;
VALUE buf = rb_str_new(0, 0);
char c, *bufs, *bufe;
from = NEXTFROM;
if (RB_TYPE_P(from, T_BIGNUM)) {
VALUE big128 = rb_uint2big(128);
while (RB_TYPE_P(from, T_BIGNUM)) {
from = rb_big_divmod(from, big128);
c = castchar(NUM2INT(RARRAY_PTR(from)[1]) | 0x80); /* mod */
rb_str_buf_cat(buf, &c, sizeof(char));
from = RARRAY_PTR(from)[0]; /* div */
}
}
{
long l = NUM2LONG(from);
if (l < 0) {
rb_raise(rb_eArgError, "can't compress negative numbers");
}
ul = l;
}
while (ul) {
c = castchar((ul & 0x7f) | 0x80);
rb_str_buf_cat(buf, &c, sizeof(char));
ul >>= 7;
}
if (RSTRING_LEN(buf)) {
bufs = RSTRING_PTR(buf);
bufe = bufs + RSTRING_LEN(buf) - 1;
*bufs &= 0x7f; /* clear continue bit */
while (bufs < bufe) { /* reverse */
c = *bufs;
*bufs++ = *bufe;
*bufe-- = c;
}
rb_str_buf_cat(res, RSTRING_PTR(buf), RSTRING_LEN(buf));
}
else {
c = 0;
rb_str_buf_cat(res, &c, sizeof(char));
}
}
break;
default:
rb_warning("unknown pack directive '%c' in '%s'",
type, RSTRING_PTR(fmt));
break;
}
}
if (associates) {
rb_str_associate(res, associates);
}
OBJ_INFECT(res, fmt);
switch (enc_info) {
case 1:
ENCODING_CODERANGE_SET(res, rb_usascii_encindex(), ENC_CODERANGE_7BIT);
break;
case 2:
rb_enc_set_index(res, rb_utf8_encindex());
break;
default:
/* do nothing, keep ASCII-8BIT */
break;
}
return res;
}
|
#permutation {|p| ... } ⇒ Object #permutation ⇒ Enumerator #permutation(n) {|p| ... } ⇒ Object #permutation(n) ⇒ Enumerator
When invoked with a block, yield all permutations of length n
of the elements of the array, then return the array itself.
If n
is not specified, yield all permutations of all elements.
The implementation makes no guarantees about the order in which the permutations are yielded.
If no block is given, an Enumerator is returned instead.
Examples:
a = [1, 2, 3]
a.permutation.to_a #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
a.permutation(1).to_a #=> [[1],[2],[3]]
a.permutation(2).to_a #=> [[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]]
a.permutation(3).to_a #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
a.permutation(0).to_a #=> [[]] # one permutation of length 0
a.permutation(4).to_a #=> [] # no permutations of length 4
4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 |
# File 'array.c', line 4649
static VALUE
rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
{
VALUE num;
long r, n, i;
n = RARRAY_LEN(ary); /* Array length */
RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_permutation_size); /* Return enumerator if no block */
rb_scan_args(argc, argv, "01", &num);
r = NIL_P(num) ? n : NUM2LONG(num); /* Permutation size from argument */
if (r < 0 || n < r) {
/* no permutations: yield nothing */
}
else if (r == 0) { /* exactly one permutation: the zero-length array */
rb_yield(rb_ary_new2(0));
}
else if (r == 1) { /* this is a special, easy case */
for (i = 0; i < RARRAY_LEN(ary); i++) {
rb_yield(rb_ary_new3(1, RARRAY_PTR(ary)[i]));
}
}
else { /* this is the general case */
volatile VALUE t0 = tmpbuf(n,sizeof(long));
long *p = (long*)RSTRING_PTR(t0);
volatile VALUE t1 = tmpbuf(n,sizeof(char));
char *used = (char*)RSTRING_PTR(t1);
VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
RBASIC(ary0)->klass = 0;
MEMZERO(used, char, n); /* initialize array */
permute0(n, r, p, 0, used, ary0); /* compute and yield permutations */
tmpbuf_discard(t0);
tmpbuf_discard(t1);
RBASIC(ary0)->klass = rb_cArray;
}
return ary;
}
|
#pop ⇒ Object? #pop(n) ⇒ Object
Removes the last element from self
and returns it, or nil
if the array is empty.
If a number n
is given, returns an array of the last n
elements (or less) just like array.slice!(-n, n)
does. See also Array#push for the opposite effect.
a = [ "a", "b", "c", "d" ]
a.pop #=> "d"
a.pop(2) #=> ["b", "c"]
a #=> ["a"]
914 915 916 917 918 919 920 921 922 923 924 925 926 927 |
# File 'array.c', line 914
static VALUE
rb_ary_pop_m(int argc, VALUE *argv, VALUE ary)
{
VALUE result;
if (argc == 0) {
return rb_ary_pop(ary);
}
rb_ary_modify_check(ary);
result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
ARY_INCREASE_LEN(ary, -RARRAY_LEN(result));
return result;
}
|
#product(other_ary, ...) ⇒ Object #product(other_ary, ...) {|p| ... } ⇒ Object
Returns an array of all combinations of elements from all arrays.
The length of the returned array is the product of the length of self
and the argument arrays.
If given a block, #product will yield all combinations and return self
instead.
[1,2,3].product([4,5]) #=> [[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]]
[1,2].product([1,2]) #=> [[1,1],[1,2],[2,1],[2,2]]
[1,2].product([3,4],[5,6]) #=> [[1,3,5],[1,3,6],[1,4,5],[1,4,6],
# [2,3,5],[2,3,6],[2,4,5],[2,4,6]]
[1,2].product() #=> [[1],[2]]
[1,2].product([]) #=> []
4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 |
# File 'array.c', line 4999
static VALUE
rb_ary_product(int argc, VALUE *argv, VALUE ary)
{
int n = argc+1; /* How many arrays we're operating on */
volatile VALUE t0 = tmpary(n);
volatile VALUE t1 = tmpbuf(n, sizeof(int));
VALUE *arrays = RARRAY_PTR(t0); /* The arrays we're computing the product of */
int *counters = (int*)RSTRING_PTR(t1); /* The current position in each one */
VALUE result = Qnil; /* The array we'll be returning, when no block given */
long i,j;
long resultlen = 1;
RBASIC(t0)->klass = 0;
RBASIC(t1)->klass = 0;
/* initialize the arrays of arrays */
ARY_SET_LEN(t0, n);
arrays[0] = ary;
for (i = 1; i < n; i++) arrays[i] = Qnil;
for (i = 1; i < n; i++) arrays[i] = to_ary(argv[i-1]);
/* initialize the counters for the arrays */
for (i = 0; i < n; i++) counters[i] = 0;
/* Otherwise, allocate and fill in an array of results */
if (rb_block_given_p()) {
/* Make defensive copies of arrays; exit if any is empty */
for (i = 0; i < n; i++) {
if (RARRAY_LEN(arrays[i]) == 0) goto done;
arrays[i] = ary_make_shared_copy(arrays[i]);
}
}
else {
/* Compute the length of the result array; return [] if any is empty */
for (i = 0; i < n; i++) {
long k = RARRAY_LEN(arrays[i]), l = resultlen;
if (k == 0) {
result = rb_ary_new2(0);
goto done;
}
resultlen *= k;
if (resultlen < k || resultlen < l || resultlen / k != l) {
rb_raise(rb_eRangeError, "too big to product");
}
}
result = rb_ary_new2(resultlen);
}
for (;;) {
int m;
/* fill in one subarray */
VALUE subarray = rb_ary_new2(n);
for (j = 0; j < n; j++) {
rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]));
}
/* put it on the result array */
if (NIL_P(result)) {
FL_SET(t0, FL_USER5);
rb_yield(subarray);
if (! FL_TEST(t0, FL_USER5)) {
rb_raise(rb_eRuntimeError, "product reentered");
}
else {
FL_UNSET(t0, FL_USER5);
}
}
else {
rb_ary_push(result, subarray);
}
/*
* Increment the last counter. If it overflows, reset to 0
* and increment the one before it.
*/
m = n-1;
counters[m]++;
while (counters[m] == RARRAY_LEN(arrays[m])) {
counters[m] = 0;
/* If the first counter overflows, we are done */
if (--m < 0) goto done;
counters[m]++;
}
}
done:
tmpary_discard(t0);
tmpbuf_discard(t1);
return NIL_P(result) ? ary : result;
}
|
#push(obj, ...) ⇒ Object
Append --- Pushes the given object(s) on to the end of this array. This expression returns the array itself, so several appends may be chained together. See also Array#pop for the opposite effect.
a = [ "a", "b", "c" ]
a.push("d", "e", "f")
#=> ["a", "b", "c", "d", "e", "f"]
[1, 2, 3,].push(4).push(5)
#=> [1, 2, 3, 4, 5]
873 874 875 876 877 |
# File 'array.c', line 873
static VALUE
rb_ary_push_m(int argc, VALUE *argv, VALUE ary)
{
return rb_ary_cat(ary, argv, argc);
}
|
#rassoc(obj) ⇒ nil
Searches through the array whose elements are also arrays.
Compares obj
with the second element of each contained array using obj.==
.
Returns the first contained array that matches obj
.
See also Array#assoc.
a = [ [ 1, "one"], [2, "two"], [3, "three"], ["ii", "two"] ]
a.rassoc("two") #=> [2, "two"]
a.rassoc("four") #=> nil
3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 |
# File 'array.c', line 3510
VALUE
rb_ary_rassoc(VALUE ary, VALUE value)
{
long i;
VALUE v;
for (i = 0; i < RARRAY_LEN(ary); ++i) {
v = RARRAY_PTR(ary)[i];
if (RB_TYPE_P(v, T_ARRAY) &&
RARRAY_LEN(v) > 1 &&
rb_equal(RARRAY_PTR(v)[1], value))
return v;
}
return Qnil;
}
|
#reject {|item| ... } ⇒ Object #reject ⇒ Enumerator
Returns a new array containing the items in self
for which the given block is not true
.
See also Array#delete_if
If no block is given, an Enumerator is returned instead.
2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 |
# File 'array.c', line 2997
static VALUE
rb_ary_reject(VALUE ary)
{
VALUE rejected_ary;
RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
rejected_ary = rb_ary_new();
ary_reject(ary, rejected_ary);
return rejected_ary;
}
|
#reject! {|item| ... } ⇒ nil #reject! ⇒ Enumerator
Equivalent to Array#delete_if, deleting elements from self
for which the block evaluates to true
, but returns nil
if no changes were made.
The array is changed instantly every time the block is called, not after the iteration is over.
See also Enumerable#reject and Array#delete_if.
If no block is given, an Enumerator is returned instead.
2977 2978 2979 2980 2981 2982 |
# File 'array.c', line 2977
static VALUE
rb_ary_reject_bang(VALUE ary)
{
RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
return ary_reject_bang(ary);
}
|
#repeated_combination(n) {|c| ... } ⇒ Object #repeated_combination(n) ⇒ Enumerator
When invoked with a block, yields all repeated combinations of length n
of elements from the array and then returns the array itself.
The implementation makes no guarantees about the order in which the repeated combinations are yielded.
If no block is given, an Enumerator is returned instead.
Examples:
a = [1, 2, 3]
a.repeated_combination(1).to_a #=> [[1], [2], [3]]
a.repeated_combination(2).to_a #=> [[1,1],[1,2],[1,3],[2,2],[2,3],[3,3]]
a.repeated_combination(3).to_a #=> [[1,1,1],[1,1,2],[1,1,3],[1,2,2],[1,2,3],
# [1,3,3],[2,2,2],[2,2,3],[2,3,3],[3,3,3]]
a.repeated_combination(4).to_a #=> [[1,1,1,1],[1,1,1,2],[1,1,1,3],[1,1,2,2],[1,1,2,3],
# [1,1,3,3],[1,2,2,2],[1,2,2,3],[1,2,3,3],[1,3,3,3],
# [2,2,2,2],[2,2,2,3],[2,2,3,3],[2,3,3,3],[3,3,3,3]]
a.repeated_combination(0).to_a #=> [[]] # one combination of length 0
4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 |
# File 'array.c', line 4943
static VALUE
rb_ary_repeated_combination(VALUE ary, VALUE num)
{
long n, i, len;
n = NUM2LONG(num); /* Combination size from argument */
RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_combination_size); /* Return enumerator if no block */
len = RARRAY_LEN(ary);
if (n < 0) {
/* yield nothing */
}
else if (n == 0) {
rb_yield(rb_ary_new2(0));
}
else if (n == 1) {
for (i = 0; i < len; i++) {
rb_yield(rb_ary_new3(1, RARRAY_PTR(ary)[i]));
}
}
else if (len == 0) {
/* yield nothing */
}
else {
volatile VALUE t0 = tmpbuf(n, sizeof(long));
long *p = (long*)RSTRING_PTR(t0);
VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
RBASIC(ary0)->klass = 0;
rcombinate0(len, n, p, 0, n, ary0); /* compute and yield repeated combinations */
tmpbuf_discard(t0);
RBASIC(ary0)->klass = rb_cArray;
}
return ary;
}
|
#repeated_permutation(n) {|p| ... } ⇒ Object #repeated_permutation(n) ⇒ Enumerator
When invoked with a block, yield all repeated permutations of length n
of the elements of the array, then return the array itself.
The implementation makes no guarantees about the order in which the repeated permutations are yielded.
If no block is given, an Enumerator is returned instead.
Examples:
a = [1, 2]
a.repeated_permutation(1).to_a #=> [[1], [2]]
a.repeated_permutation(2).to_a #=> [[1,1],[1,2],[2,1],[2,2]]
a.repeated_permutation(3).to_a #=> [[1,1,1],[1,1,2],[1,2,1],[1,2,2],
# [2,1,1],[2,1,2],[2,2,1],[2,2,2]]
a.repeated_permutation(0).to_a #=> [[]] # one permutation of length 0
4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 |
# File 'array.c', line 4848
static VALUE
rb_ary_repeated_permutation(VALUE ary, VALUE num)
{
long r, n, i;
n = RARRAY_LEN(ary); /* Array length */
RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_permutation_size); /* Return Enumerator if no block */
r = NUM2LONG(num); /* Permutation size from argument */
if (r < 0) {
/* no permutations: yield nothing */
}
else if (r == 0) { /* exactly one permutation: the zero-length array */
rb_yield(rb_ary_new2(0));
}
else if (r == 1) { /* this is a special, easy case */
for (i = 0; i < RARRAY_LEN(ary); i++) {
rb_yield(rb_ary_new3(1, RARRAY_PTR(ary)[i]));
}
}
else { /* this is the general case */
volatile VALUE t0 = tmpbuf(r, sizeof(long));
long *p = (long*)RSTRING_PTR(t0);
VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
RBASIC(ary0)->klass = 0;
rpermute0(n, r, p, 0, ary0); /* compute and yield repeated permutations */
tmpbuf_discard(t0);
RBASIC(ary0)->klass = rb_cArray;
}
return ary;
}
|
#replace(other_ary) ⇒ Object
Replaces the contents of self
with the contents of other_ary
, truncating or expanding if necessary.
a = [ "a", "b", "c", "d", "e" ]
a.replace([ "x", "y", "z" ]) #=> ["x", "y", "z"]
a #=> ["x", "y", "z"]
3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 |
# File 'array.c', line 3168
VALUE
rb_ary_replace(VALUE copy, VALUE orig)
{
rb_ary_modify_check(copy);
orig = to_ary(orig);
if (copy == orig) return copy;
if (RARRAY_LEN(orig) <= RARRAY_EMBED_LEN_MAX) {
VALUE *ptr;
VALUE shared = 0;
if (ARY_OWNS_HEAP_P(copy)) {
xfree(RARRAY_PTR(copy));
}
else if (ARY_SHARED_P(copy)) {
shared = ARY_SHARED(copy);
FL_UNSET_SHARED(copy);
}
FL_SET_EMBED(copy);
ptr = RARRAY_PTR(orig);
MEMCPY(RARRAY_PTR(copy), ptr, VALUE, RARRAY_LEN(orig));
if (shared) {
rb_ary_decrement_share(shared);
}
ARY_SET_LEN(copy, RARRAY_LEN(orig));
}
else {
VALUE shared = ary_make_shared(orig);
if (ARY_OWNS_HEAP_P(copy)) {
xfree(RARRAY_PTR(copy));
}
else {
rb_ary_unshare_safe(copy);
}
FL_UNSET_EMBED(copy);
ARY_SET_PTR(copy, RARRAY_PTR(orig));
ARY_SET_LEN(copy, RARRAY_LEN(orig));
rb_ary_set_shared(copy, shared);
}
return copy;
}
|
#reverse ⇒ Object
Returns a new array containing self
's elements in reverse order.
[ "a", "b", "c" ].reverse #=> ["c", "b", "a"]
[ 1 ].reverse #=> [1]
2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 |
# File 'array.c', line 2084
static VALUE
rb_ary_reverse_m(VALUE ary)
{
long len = RARRAY_LEN(ary);
VALUE dup = rb_ary_new2(len);
if (len > 0) {
VALUE *p1 = RARRAY_PTR(ary);
VALUE *p2 = RARRAY_PTR(dup) + len - 1;
do *p2-- = *p1++; while (--len > 0);
}
ARY_SET_LEN(dup, RARRAY_LEN(ary));
return dup;
}
|
#reverse! ⇒ Object
Reverses self
in place.
a = [ "a", "b", "c" ]
a.reverse! #=> ["c", "b", "a"]
a #=> ["c", "b", "a"]
2068 2069 2070 2071 2072 |
# File 'array.c', line 2068
static VALUE
rb_ary_reverse_bang(VALUE ary)
{
return rb_ary_reverse(ary);
}
|
#reverse_each {|item| ... } ⇒ Object #reverse_each ⇒ Enumerator
Same as Array#each, but traverses self
in reverse order.
a = [ "a", "b", "c" ]
a.reverse_each {|x| print x, " " }
produces:
c b a
1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 |
# File 'array.c', line 1728
static VALUE
rb_ary_reverse_each(VALUE ary)
{
long len;
RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
len = RARRAY_LEN(ary);
while (len--) {
rb_yield(RARRAY_PTR(ary)[len]);
if (RARRAY_LEN(ary) < len) {
len = RARRAY_LEN(ary);
}
}
return ary;
}
|
#rindex(obj) ⇒ Integer? #rindex {|item| ... } ⇒ Integer? #rindex ⇒ Enumerator
Returns the index of the last object in self
==
to obj
.
If a block is given instead of an argument, returns the index of the first object for which the block returns true
, starting from the last object.
Returns nil
if no match is found.
See also Array#index.
If neither block nor argument is given, an Enumerator is returned instead.
a = [ "a", "b", "b", "b", "c" ]
a.rindex("b") #=> 3
a.rindex("z") #=> nil
a.rindex { |x| x == "b" } #=> 3
1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 |
# File 'array.c', line 1395
static VALUE
rb_ary_rindex(int argc, VALUE *argv, VALUE ary)
{
VALUE val;
long i = RARRAY_LEN(ary);
if (argc == 0) {
RETURN_ENUMERATOR(ary, 0, 0);
while (i--) {
if (RTEST(rb_yield(RARRAY_PTR(ary)[i])))
return LONG2NUM(i);
if (i > RARRAY_LEN(ary)) {
i = RARRAY_LEN(ary);
}
}
return Qnil;
}
rb_scan_args(argc, argv, "1", &val);
if (rb_block_given_p())
rb_warn("given block not used");
while (i--) {
if (rb_equal(RARRAY_PTR(ary)[i], val))
return LONG2NUM(i);
if (i > RARRAY_LEN(ary)) {
i = RARRAY_LEN(ary);
}
}
return Qnil;
}
|
#rotate(count = 1) ⇒ Object
Returns a new array by rotating self
so that the element at count
is the first element of the new array.
If count
is negative then it rotates in the opposite direction, starting from the end of self
where -1
is the last element.
a = [ "a", "b", "c", "d" ]
a.rotate #=> ["b", "c", "d", "a"]
a #=> ["a", "b", "c", "d"]
a.rotate(2) #=> ["c", "d", "a", "b"]
a.rotate(-3) #=> ["b", "c", "d", "a"]
2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 |
# File 'array.c', line 2174
static VALUE
rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary)
{
VALUE rotated, *ptr, *ptr2;
long len, cnt = 1;
switch (argc) {
case 1: cnt = NUM2LONG(argv[0]);
case 0: break;
default: rb_scan_args(argc, argv, "01", NULL);
}
len = RARRAY_LEN(ary);
rotated = rb_ary_new2(len);
if (len > 0) {
cnt = rotate_count(cnt, len);
ptr = RARRAY_PTR(ary);
ptr2 = RARRAY_PTR(rotated);
len -= cnt;
MEMCPY(ptr2, ptr + cnt, VALUE, len);
MEMCPY(ptr2 + len, ptr, VALUE, cnt);
}
ARY_SET_LEN(rotated, RARRAY_LEN(ary));
return rotated;
}
|
#rotate!(count = 1) ⇒ Object
Rotates self
in place so that the element at count
comes first, and returns self
.
If count
is negative then it rotates in the opposite direction, starting from the end of the array where -1
is the last element.
a = [ "a", "b", "c", "d" ]
a.rotate! #=> ["b", "c", "d", "a"]
a #=> ["b", "c", "d", "a"]
a.rotate!(2) #=> ["d", "a", "b", "c"]
a.rotate!(-3) #=> ["a", "b", "c", "d"]
2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 |
# File 'array.c', line 2143
static VALUE
rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
{
long n = 1;
switch (argc) {
case 1: n = NUM2LONG(argv[0]);
case 0: break;
default: rb_scan_args(argc, argv, "01", NULL);
}
rb_ary_rotate(ary, n);
return ary;
}
|
#sample ⇒ Object #sample(random:rng) ⇒ Object #sample(n) ⇒ Object #sample(n, random:rng) ⇒ Object
Choose a random element or n
random elements from the array.
The elements are chosen by using random and unique indices into the array in order to ensure that an element doesn't repeat itself unless the array already contained duplicate elements.
If the array is empty the first form returns nil
and the second form returns an empty array.
The optional rng
argument will be used as the random number generator.
a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
a.sample #=> 7
a.sample(4) #=> [6, 4, 2, 5]
4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 |
# File 'array.c', line 4368
static VALUE
rb_ary_sample(int argc, VALUE *argv, VALUE ary)
{
VALUE nv, result, *ptr;
VALUE opts, randgen = rb_cRandom;
long n, len, i, j, k, idx[10];
long rnds[numberof(idx)];
if (OPTHASH_GIVEN_P(opts)) {
randgen = rb_hash_lookup2(opts, sym_random, randgen);
}
ptr = RARRAY_PTR(ary);
len = RARRAY_LEN(ary);
if (argc == 0) {
if (len == 0) return Qnil;
if (len == 1) {
i = 0;
}
else {
i = RAND_UPTO(len);
if ((len = RARRAY_LEN(ary)) <= i) return Qnil;
ptr = RARRAY_PTR(ary);
}
return ptr[i];
}
rb_scan_args(argc, argv, "1", &nv);
n = NUM2LONG(nv);
if (n < 0) rb_raise(rb_eArgError, "negative sample number");
if (n > len) n = len;
if (n <= numberof(idx)) {
for (i = 0; i < n; ++i) {
rnds[i] = RAND_UPTO(len - i);
}
}
k = len;
len = RARRAY_LEN(ary);
ptr = RARRAY_PTR(ary);
if (len < k) {
if (n <= numberof(idx)) {
for (i = 0; i < n; ++i) {
if (rnds[i] >= len) {
return rb_ary_new2(0);
}
}
}
}
if (n > len) n = len;
switch (n) {
case 0:
return rb_ary_new2(0);
case 1:
i = rnds[0];
return rb_ary_new4(1, &ptr[i]);
case 2:
i = rnds[0];
j = rnds[1];
if (j >= i) j++;
return rb_ary_new3(2, ptr[i], ptr[j]);
case 3:
i = rnds[0];
j = rnds[1];
k = rnds[2];
{
long l = j, g = i;
if (j >= i) l = i, g = ++j;
if (k >= l && (++k >= g)) ++k;
}
return rb_ary_new3(3, ptr[i], ptr[j], ptr[k]);
}
if (n <= numberof(idx)) {
VALUE *ptr_result;
long sorted[numberof(idx)];
sorted[0] = idx[0] = rnds[0];
for (i=1; i<n; i++) {
k = rnds[i];
for (j = 0; j < i; ++j) {
if (k < sorted[j]) break;
++k;
}
memmove(&sorted[j+1], &sorted[j], sizeof(sorted[0])*(i-j));
sorted[j] = idx[i] = k;
}
result = rb_ary_new2(n);
ptr_result = RARRAY_PTR(result);
for (i=0; i<n; i++) {
ptr_result[i] = ptr[idx[i]];
}
}
else {
VALUE *ptr_result;
result = rb_ary_new4(len, ptr);
RBASIC(result)->klass = 0;
ptr_result = RARRAY_PTR(result);
RB_GC_GUARD(ary);
for (i=0; i<n; i++) {
j = RAND_UPTO(len-i) + i;
nv = ptr_result[j];
ptr_result[j] = ptr_result[i];
ptr_result[i] = nv;
}
RBASIC(result)->klass = rb_cArray;
}
ARY_SET_LEN(result, n);
return result;
}
|
#select {|item| ... } ⇒ Object #select ⇒ Enumerator
Returns a new array containing all elements of ary
for which the given block
returns a true value.
If no block is given, an Enumerator is returned instead.
[1,2,3,4,5].select { |num| num.even? } #=> [2, 4]
a = %w{ a b c d e f }
a.select { |v| v =~ /[aeiou]/ } #=> ["a", "e"]
See also Enumerable#select.
2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 |
# File 'array.c', line 2649
static VALUE
rb_ary_select(VALUE ary)
{
VALUE result;
long i;
RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
result = rb_ary_new2(RARRAY_LEN(ary));
for (i = 0; i < RARRAY_LEN(ary); i++) {
if (RTEST(rb_yield(RARRAY_PTR(ary)[i]))) {
rb_ary_push(result, rb_ary_elt(ary, i));
}
}
return result;
}
|
#select! {|item| ... } ⇒ nil #select! ⇒ Enumerator
Invokes the given block passing in successive elements from self
, deleting elements for which the block returns a false
value.
If changes were made, it will return self
, otherwise it returns nil
.
See also Array#keep_if
If no block is given, an Enumerator is returned instead.
2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 |
# File 'array.c', line 2681
static VALUE
rb_ary_select_bang(VALUE ary)
{
long i1, i2;
RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
rb_ary_modify(ary);
for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
VALUE v = RARRAY_PTR(ary)[i1];
if (!RTEST(rb_yield(v))) continue;
if (i1 != i2) {
rb_ary_store(ary, i2, v);
}
i2++;
}
if (RARRAY_LEN(ary) == i2) return Qnil;
if (i2 < RARRAY_LEN(ary))
ARY_SET_LEN(ary, i2);
return ary;
}
|
#shift ⇒ Object? #shift(n) ⇒ Object
Removes the first element of self
and returns it (shifting all other elements down by one). Returns nil
if the array is empty.
If a number n
is given, returns an array of the first n
elements (or less) just like array.slice!(0, n)
does. With ary
containing only the remainder elements, not including what was shifted to new_ary
. See also Array#unshift for the opposite effect.
args = [ "-m", "-q", "filename" ]
args.shift #=> "-m"
args #=> ["-q", "filename"]
args = [ "-m", "-q", "filename" ]
args.shift(2) #=> ["-m", "-q"]
args #=> ["filename"]
980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 |
# File 'array.c', line 980
static VALUE
rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
{
VALUE result;
long n;
if (argc == 0) {
return rb_ary_shift(ary);
}
rb_ary_modify_check(ary);
result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
n = RARRAY_LEN(result);
if (ARY_SHARED_P(ary)) {
if (ARY_SHARED_NUM(ARY_SHARED(ary)) == 1) {
rb_mem_clear(RARRAY_PTR(ary), n);
}
ARY_INCREASE_PTR(ary, n);
}
else {
MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+n, VALUE, RARRAY_LEN(ary)-n);
}
ARY_INCREASE_LEN(ary, -n);
return result;
}
|
#shuffle ⇒ Object #shuffle(random:rng) ⇒ Object
4335 4336 4337 4338 4339 4340 4341 |
# File 'array.c', line 4335
static VALUE
rb_ary_shuffle(int argc, VALUE *argv, VALUE ary)
{
ary = rb_ary_dup(ary);
rb_ary_shuffle_bang(argc, argv, ary);
return ary;
}
|
#shuffle! ⇒ Object #shuffle!(random:rng) ⇒ Object
Shuffles elements in self
in place.
The optional rng
argument will be used as the random number generator.
4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 |
# File 'array.c', line 4291
static VALUE
rb_ary_shuffle_bang(int argc, VALUE *argv, VALUE ary)
{
VALUE *ptr, opts, *snap_ptr, randgen = rb_cRandom;
long i, snap_len;
if (OPTHASH_GIVEN_P(opts)) {
randgen = rb_hash_lookup2(opts, sym_random, randgen);
}
rb_check_arity(argc, 0, 0);
rb_ary_modify(ary);
i = RARRAY_LEN(ary);
ptr = RARRAY_PTR(ary);
snap_len = i;
snap_ptr = ptr;
while (i) {
long j = RAND_UPTO(i);
VALUE tmp;
if (snap_len != RARRAY_LEN(ary) || snap_ptr != RARRAY_PTR(ary)) {
rb_raise(rb_eRuntimeError, "modified during shuffle");
}
tmp = ptr[--i];
ptr[i] = ptr[j];
ptr[j] = tmp;
}
return ary;
}
|
#[](index) ⇒ Object? #[](start, length) ⇒ nil #[](range) ⇒ nil #slice(index) ⇒ Object? #slice(start, length) ⇒ nil #slice(range) ⇒ nil
Element Reference --- Returns the element at index
, or returns a subarray starting at the start
index and continuing for length
elements, or returns a subarray specified by range
of indices.
Negative indices count backward from the end of the array (-1 is the last element). 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.
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] #=> []
1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 |
# File 'array.c', line 1163
VALUE
rb_ary_aref(int argc, VALUE *argv, VALUE ary)
{
VALUE arg;
long beg, len;
if (argc == 2) {
beg = NUM2LONG(argv[0]);
len = NUM2LONG(argv[1]);
if (beg < 0) {
beg += RARRAY_LEN(ary);
}
return rb_ary_subseq(ary, beg, len);
}
if (argc != 1) {
rb_scan_args(argc, argv, "11", NULL, NULL);
}
arg = argv[0];
/* special case - speeding up */
if (FIXNUM_P(arg)) {
return rb_ary_entry(ary, FIX2LONG(arg));
}
/* check if idx is Range */
switch (rb_range_beg_len(arg, &beg, &len, RARRAY_LEN(ary), 0)) {
case Qfalse:
break;
case Qnil:
return Qnil;
default:
return rb_ary_subseq(ary, beg, len);
}
return rb_ary_entry(ary, NUM2LONG(arg));
}
|
#slice!(index) ⇒ Object? #slice!(start, length) ⇒ nil #slice!(range) ⇒ nil
Deletes the element(s) given by an index
(optionally up to length
elements) or by a range
.
Returns the deleted object (or objects), or nil
if the index
is out of range.
a = [ "a", "b", "c" ]
a.slice!(1) #=> "b"
a #=> ["a", "c"]
a.slice!(-1) #=> "c"
a #=> ["a"]
a.slice!(100) #=> nil
a #=> ["a"]
2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 |
# File 'array.c', line 2876
static VALUE
rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary)
{
VALUE arg1, arg2;
long pos, len, orig_len;
rb_ary_modify_check(ary);
if (argc == 2) {
pos = NUM2LONG(argv[0]);
len = NUM2LONG(argv[1]);
delete_pos_len:
if (len < 0) return Qnil;
orig_len = RARRAY_LEN(ary);
if (pos < 0) {
pos += orig_len;
if (pos < 0) return Qnil;
}
else if (orig_len < pos) return Qnil;
if (orig_len < pos + len) {
len = orig_len - pos;
}
if (len == 0) return rb_ary_new2(0);
arg2 = rb_ary_new4(len, RARRAY_PTR(ary)+pos);
RBASIC(arg2)->klass = rb_obj_class(ary);
rb_ary_splice(ary, pos, len, Qundef);
return arg2;
}
if (argc != 1) {
/* error report */
rb_scan_args(argc, argv, "11", NULL, NULL);
}
arg1 = argv[0];
if (!FIXNUM_P(arg1)) {
switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
case Qtrue:
/* valid range */
goto delete_pos_len;
case Qnil:
/* invalid range */
return Qnil;
default:
/* not a range */
break;
}
}
return rb_ary_delete_at(ary, NUM2LONG(arg1));
}
|
#sort ⇒ Object #sort {|a, b| ... } ⇒ Object
Returns a new array created by sorting self
.
Comparisons for the sort will be done using the <=>
operator or using an optional code block.
The block must implement a comparison between a
and b
, and return -1
, when a
follows b
, 0
when a
and b
are equivalent, or +1
if b
follows a
.
See also Enumerable#sort_by.
a = [ "d", "a", "e", "c", "b" ]
a.sort #=> ["a", "b", "c", "d", "e"]
a.sort { |x,y| y <=> x } #=> ["e", "d", "c", "b", "a"]
2373 2374 2375 2376 2377 2378 2379 |
# File 'array.c', line 2373
VALUE
rb_ary_sort(VALUE ary)
{
ary = rb_ary_dup(ary);
rb_ary_sort_bang(ary);
return ary;
}
|
#sort! ⇒ Object #sort! {|a, b| ... } ⇒ Object
Sorts self
in place.
Comparisons for the sort will be done using the <=>
operator or using an optional code block.
The block must implement a comparison between a
and b
, and return -1
, when a
follows b
, 0
when a
and b
are equivalent, or +1
if b
follows a
.
See also Enumerable#sort_by.
a = [ "d", "a", "e", "c", "b" ]
a.sort! #=> ["a", "b", "c", "d", "e"]
a.sort! { |x,y| y <=> x } #=> ["e", "d", "c", "b", "a"]
2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 |
# File 'array.c', line 2290
VALUE
rb_ary_sort_bang(VALUE ary)
{
rb_ary_modify(ary);
assert(!ARY_SHARED_P(ary));
if (RARRAY_LEN(ary) > 1) {
VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */
struct ary_sort_data data;
long len = RARRAY_LEN(ary);
RBASIC(tmp)->klass = 0;
data.ary = tmp;
data.opt_methods = 0;
data.opt_inited = 0;
ruby_qsort(RARRAY_PTR(tmp), len, sizeof(VALUE),
rb_block_given_p()?sort_1:sort_2, &data);
if (ARY_EMBED_P(tmp)) {
assert(ARY_EMBED_P(tmp));
if (ARY_SHARED_P(ary)) { /* ary might be destructively operated in the given block */
rb_ary_unshare(ary);
}
FL_SET_EMBED(ary);
MEMCPY(RARRAY_PTR(ary), ARY_EMBED_PTR(tmp), VALUE, ARY_EMBED_LEN(tmp));
ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp));
}
else {
assert(!ARY_EMBED_P(tmp));
if (ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) {
assert(!ARY_EMBED_P(ary));
FL_UNSET_SHARED(ary);
ARY_SET_CAPA(ary, RARRAY_LEN(tmp));
}
else {
assert(!ARY_SHARED_P(tmp));
if (ARY_EMBED_P(ary)) {
FL_UNSET_EMBED(ary);
}
else if (ARY_SHARED_P(ary)) {
/* ary might be destructively operated in the given block */
rb_ary_unshare(ary);
}
else {
xfree(ARY_HEAP_PTR(ary));
}
ARY_SET_PTR(ary, RARRAY_PTR(tmp));
ARY_SET_HEAP_LEN(ary, len);
ARY_SET_CAPA(ary, RARRAY_LEN(tmp));
}
/* tmp was lost ownership for the ptr */
FL_UNSET(tmp, FL_FREEZE);
FL_SET_EMBED(tmp);
ARY_SET_EMBED_LEN(tmp, 0);
FL_SET(tmp, FL_FREEZE);
}
/* tmp will be GC'ed. */
RBASIC(tmp)->klass = rb_cArray;
}
return ary;
}
|
#sort_by! {|obj| ... } ⇒ Object #sort_by! ⇒ Enumerator
Sorts self
in place using a set of keys generated by mapping the values in self
through the given block.
If no block is given, an Enumerator is returned instead.
2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 |
# File 'array.c', line 2500
static VALUE
rb_ary_sort_by_bang(VALUE ary)
{
VALUE sorted;
RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
rb_ary_modify(ary);
sorted = rb_block_call(ary, rb_intern("sort_by"), 0, 0, sort_by_i, 0);
rb_ary_replace(ary, sorted);
return ary;
}
|
#take(n) ⇒ Object
Returns first n
elements from the array.
If a negative number is given, raises an ArgumentError.
See also Array#drop
a = [1, 2, 3, 4, 5, 0]
a.take(3) #=> [1, 2, 3]
5104 5105 5106 5107 5108 5109 5110 5111 5112 |
# File 'array.c', line 5104
static VALUE
rb_ary_take(VALUE obj, VALUE n)
{
long len = NUM2LONG(n);
if (len < 0) {
rb_raise(rb_eArgError, "attempt to take negative size");
}
return rb_ary_subseq(obj, 0, len);
}
|
#take_while {|arr| ... } ⇒ Object #take_while ⇒ Enumerator
Passes elements to the block until the block returns nil
or false
, then stops iterating and returns an array of all prior elements.
If no block is given, an Enumerator is returned instead.
See also Array#drop_while
a = [1, 2, 3, 4, 5, 0]
a.take_while { |i| i < 3 } #=> [1, 2]
5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 |
# File 'array.c', line 5131
static VALUE
rb_ary_take_while(VALUE ary)
{
long i;
RETURN_ENUMERATOR(ary, 0, 0);
for (i = 0; i < RARRAY_LEN(ary); i++) {
if (!RTEST(rb_yield(RARRAY_PTR(ary)[i]))) break;
}
return rb_ary_take(ary, LONG2FIX(i));
}
|
#to_a ⇒ Object
Returns self
.
If called on a subclass of Array, converts the receiver to an Array object.
2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 |
# File 'array.c', line 2009
static VALUE
rb_ary_to_a(VALUE ary)
{
if (rb_obj_class(ary) != rb_cArray) {
VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
rb_ary_replace(dup, ary);
return dup;
}
return ary;
}
|
#to_ary ⇒ Object
Returns self
.
2027 2028 2029 2030 2031 |
# File 'array.c', line 2027
static VALUE
rb_ary_to_ary_m(VALUE ary)
{
return ary;
}
|
#transpose ⇒ Object
Assumes that self
is an array of arrays and transposes the rows and columns.
a = [[1,2], [3,4], [5,6]]
a.transpose #=> [[1, 3, 5], [2, 4, 6]]
If the length of the subarrays don't match, an IndexError is raised.
3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 |
# File 'array.c', line 3128
static VALUE
rb_ary_transpose(VALUE ary)
{
long elen = -1, alen, i, j;
VALUE tmp, result = 0;
alen = RARRAY_LEN(ary);
if (alen == 0) return rb_ary_dup(ary);
for (i=0; i<alen; i++) {
tmp = to_ary(rb_ary_elt(ary, i));
if (elen < 0) { /* first element */
elen = RARRAY_LEN(tmp);
result = rb_ary_new2(elen);
for (j=0; j<elen; j++) {
rb_ary_store(result, j, rb_ary_new2(alen));
}
}
else if (elen != RARRAY_LEN(tmp)) {
rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
RARRAY_LEN(tmp), elen);
}
for (j=0; j<elen; j++) {
rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
}
}
return result;
}
|
#uniq ⇒ Object #uniq {|item| ... } ⇒ Object
Returns a new array by removing duplicate values in self
.
If a block is given, it will use the return value of the block for comparison.
It compares values using their #hash and #eql? methods for efficiency.
a = [ "a", "a", "b", "b", "c" ]
a.uniq # => ["a", "b", "c"]
b = [["student","sam"], ["student","george"], ["teacher","matz"]]
b.uniq { |s| s.first } # => [["student", "sam"], ["teacher", "matz"]]
4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 |
# File 'array.c', line 4005
static VALUE
rb_ary_uniq(VALUE ary)
{
VALUE hash, uniq, v;
long i;
if (RARRAY_LEN(ary) <= 1)
return rb_ary_dup(ary);
if (rb_block_given_p()) {
hash = ary_make_hash_by(ary);
uniq = ary_new(rb_obj_class(ary), RHASH_SIZE(hash));
st_foreach(RHASH_TBL(hash), push_value, uniq);
}
else {
hash = ary_make_hash(ary);
uniq = ary_new(rb_obj_class(ary), RHASH_SIZE(hash));
for (i=0; i<RARRAY_LEN(ary); i++) {
st_data_t vv = (st_data_t)(v = rb_ary_elt(ary, i));
if (st_delete(RHASH_TBL(hash), &vv, 0)) {
rb_ary_push(uniq, v);
}
}
}
ary_recycle_hash(hash);
return uniq;
}
|
#uniq! ⇒ nil #uniq! {|item| ... } ⇒ nil
Removes duplicate elements from self
.
If a block is given, it will use the return value of the block for comparison.
It compares values using their #hash and #eql? methods for efficiency.
Returns nil
if no changes are made (that is, no duplicates are found).
a = [ "a", "a", "b", "b", "c" ]
a.uniq! # => ["a", "b", "c"]
b = [ "a", "b", "c" ]
b.uniq! # => nil
c = [["student","sam"], ["student","george"], ["teacher","matz"]]
c.uniq! { |s| s.first } # => [["student", "sam"], ["teacher", "matz"]]
3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 |
# File 'array.c', line 3946
static VALUE
rb_ary_uniq_bang(VALUE ary)
{
VALUE hash, v;
long i, j;
rb_ary_modify_check(ary);
if (RARRAY_LEN(ary) <= 1)
return Qnil;
if (rb_block_given_p()) {
hash = ary_make_hash_by(ary);
if (RARRAY_LEN(ary) == (i = RHASH_SIZE(hash))) {
return Qnil;
}
ARY_SET_LEN(ary, 0);
if (ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) {
rb_ary_unshare(ary);
FL_SET_EMBED(ary);
}
ary_resize_capa(ary, i);
st_foreach(RHASH_TBL(hash), push_value, ary);
}
else {
hash = ary_make_hash(ary);
if (RARRAY_LEN(ary) == (long)RHASH_SIZE(hash)) {
return Qnil;
}
for (i=j=0; i<RARRAY_LEN(ary); i++) {
st_data_t vv = (st_data_t)(v = rb_ary_elt(ary, i));
if (st_delete(RHASH_TBL(hash), &vv, 0)) {
rb_ary_store(ary, j++, v);
}
}
ARY_SET_LEN(ary, j);
}
ary_recycle_hash(hash);
return ary;
}
|
#unshift(obj, ...) ⇒ Object
Prepends objects to the front of self
, moving other elements upwards. See also Array#shift for the opposite effect.
a = [ "b", "c", "d" ]
a.unshift("a") #=> ["a", "b", "c", "d"]
a.unshift(1, 2) #=> [ 1, 2, "a", "b", "c", "d"]
1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 |
# File 'array.c', line 1068
static VALUE
rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
{
long len = RARRAY_LEN(ary);
if (argc == 0) {
rb_ary_modify_check(ary);
return ary;
}
ary_ensure_room_for_unshift(ary, argc);
MEMCPY(RARRAY_PTR(ary), argv, VALUE, argc);
ARY_SET_LEN(ary, len + argc);
return ary;
}
|
#values_at(selector, ...) ⇒ Object
Returns an array containing the elements in self
corresponding to the given selector
(s).
The selectors may be either integer indices or ranges.
See also Array#select.
a = %w{ a b c d e f }
a.values_at(1, 3, 5) # => ["b", "d", "f"]
a.values_at(1, 3, 5, 7) # => ["b", "d", "f", nil]
a.values_at(-1, -2, -2, -7) # => ["f", "e", "e", nil]
a.values_at(4..6, 3...6) # => ["e", "f", nil, "d", "e", "f"]
2624 2625 2626 2627 2628 |
# File 'array.c', line 2624
static VALUE
rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
{
return rb_get_values_at(ary, RARRAY_LEN(ary), argc, argv, rb_ary_entry);
}
|
#zip(arg, ...) ⇒ Object #zip(arg, ...) {|arr| ... } ⇒ nil
Converts any arguments to arrays, then merges elements of self
with corresponding elements from each argument.
This generates a sequence of ary.size
n-element arrays, where n is one more that the count of arguments.
If the size of any argument is less than the size of the initial array, nil
values are supplied.
If a block is given, it is invoked for each output array
, otherwise an array of arrays is returned.
a = [ 4, 5, 6 ]
b = [ 7, 8, 9 ]
[1, 2, 3].zip(a, b) #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
[1, 2].zip(a, b) #=> [[1, 4, 7], [2, 5, 8]]
a.zip([1, 2], [8]) #=> [[4, 1, 8], [5, 2, nil], [6, nil, nil]]
3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 |
# File 'array.c', line 3083
static VALUE
rb_ary_zip(int argc, VALUE *argv, VALUE ary)
{
int i, j;
long len;
VALUE result = Qnil;
len = RARRAY_LEN(ary);
for (i=0; i<argc; i++) {
argv[i] = take_items(argv[i], len);
}
if (!rb_block_given_p()) {
result = rb_ary_new2(len);
}
for (i=0; i<RARRAY_LEN(ary); i++) {
VALUE tmp = rb_ary_new2(argc+1);
rb_ary_push(tmp, rb_ary_elt(ary, i));
for (j=0; j<argc; j++) {
rb_ary_push(tmp, rb_ary_elt(argv[j], i));
}
if (NIL_P(result)) {
rb_yield(tmp);
}
else {
rb_ary_push(result, tmp);
}
}
return result;
}
|
#|(other_ary) ⇒ Object
Set Union --- Returns a new array by joining ary
with other_ary
, excluding any duplicates.
It compares elements using their #hash and #eql? methods for efficiency.
[ "a", "b", "c" ] | [ "c", "d", "a" ] #=> [ "a", "b", "c", "d" ]
See also Array#uniq.
3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 |
# File 'array.c', line 3887
static VALUE
rb_ary_or(VALUE ary1, VALUE ary2)
{
VALUE hash, ary3, v;
st_data_t vv;
long i;
ary2 = to_ary(ary2);
ary3 = rb_ary_new2(RARRAY_LEN(ary1)+RARRAY_LEN(ary2));
hash = ary_add_hash(ary_make_hash(ary1), ary2);
for (i=0; i<RARRAY_LEN(ary1); i++) {
vv = (st_data_t)(v = rb_ary_elt(ary1, i));
if (st_delete(RHASH_TBL(hash), &vv, 0)) {
rb_ary_push(ary3, v);
}
}
for (i=0; i<RARRAY_LEN(ary2); i++) {
vv = (st_data_t)(v = rb_ary_elt(ary2, i));
if (st_delete(RHASH_TBL(hash), &vv, 0)) {
rb_ary_push(ary3, v);
}
}
ary_recycle_hash(hash);
return ary3;
}
|