From 06e3f3495a9d7b0b9152fcd4611cbdc4eca0c126 Mon Sep 17 00:00:00 2001 From: drbrain Date: Mon, 10 Oct 2011 22:55:54 +0000 Subject: [PATCH] * array.c: Add a description to Array, minor cleanups. Patch by Andrea Singh. [Ruby 1.9 - Bug #5412] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33451 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 5 ++ array.c | 259 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 248 insertions(+), 16 deletions(-) diff --git a/ChangeLog b/ChangeLog index e2963225a6..ec390f96c8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Tue Oct 11 07:55:38 2011 Eric Hodel + + * array.c: Add a description to Array, minor cleanups. Patch by + Andrea Singh. [Ruby 1.9 - Bug #5412] + Tue Oct 11 06:09:52 2011 Eric Hodel * lib/pp.rb: Move PP documentation to top of class PP. Patch by diff --git a/array.c b/array.c index a416cc2ec5..d44d9c0545 100644 --- a/array.c +++ b/array.c @@ -1107,11 +1107,19 @@ rb_ary_last(int argc, VALUE *argv, VALUE ary) * block, passing in the index. Negative values of +index+ count from the end * of the array. * + * 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 the second argument is a block 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(4) { |i| i*i } #=> 16 + * a.fetch(100) { |i| puts "#{i} is out of bounds" } + * #=> "100 is out of bounds" */ static VALUE @@ -2216,8 +2224,8 @@ rb_ary_sort_by_bang(VALUE ary) * If no block is given, an enumerator is returned instead. * * a = [ "a", "b", "c", "d" ] - * a.collect {|x| x + "!" } #=> ["a!", "b!", "c!", "d!"] - * a #=> ["a", "b", "c", "d"] + * a.map {|x| x + "!" } #=> ["a!", "b!", "c!", "d!"] + * a #=> ["a", "b", "c", "d"] */ static VALUE @@ -2249,8 +2257,8 @@ rb_ary_collect(VALUE ary) * If no block is given, an enumerator is returned instead. * * a = [ "a", "b", "c", "d" ] - * a.collect! {|x| x + "!" } - * a #=> [ "a!", "b!", "c!", "d!" ] + * a.map! {|x| x + "!" } + * a #=> [ "a!", "b!", "c!", "d!" ] */ static VALUE @@ -3300,13 +3308,14 @@ recursive_cmp(VALUE ary1, VALUE ary2, int recur) * * 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 <=>). If any value isn't - * equal, then that inequality is the return value. If all the - * values found 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 + * +other_ary+. + * + * Each object in each array is compared (using <=>). 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 @@ -3660,7 +3669,8 @@ rb_ary_compact(VALUE ary) * * Returns the number of elements. If an argument is given, counts * the number of elements which equals to +obj+. If a block is - * given, counts the number of elements yielding a true value. + * given, counts the number of elements for which the block returns a true + * value. * * ary = [1, 2, 4, 2] * ary.count #=> 4 @@ -4637,13 +4647,229 @@ rb_ary_drop_while(VALUE ary) return rb_ary_drop(ary, LONG2FIX(i)); } - - -/* Arrays are ordered, integer-indexed collections of any object. +/* + * 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 the same + * object. Therefore, it is only recommended in cases when you need to + * instantiate arrays with natively immutable objects such 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]] + * + * == 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 a non-destructive (#uniq) and a 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] + * */ void @@ -4760,3 +4986,4 @@ Init_Array(void) id_cmp = rb_intern("<=>"); sym_random = ID2SYM(rb_intern("random")); } +