Class: Array

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
mrblib/array.rb,
src/array.c,
mrblib/array.rb,
mrbgems/mruby-array-ext/mrblib/array.rb

Overview

Array is enumerable

Constant Summary

Constants included from Enumerable

Enumerable::NONE

Instance Method Summary collapse

Methods included from Enumerable

__update_hash, #all?, #any?, #chain, #collect, #count, #cycle, #detect, #drop, #drop_while, #each_cons, #each_slice, #each_with_index, #each_with_object, #entries, #filter_map, #find_all, #find_index, #flat_map, #grep, #group_by, #hash, #include?, #inject, #lazy, #max, #max_by, #min, #min_by, #minmax, #minmax_by, #none?, #one?, #partition, #reject, #sort_by, #take, #take_while, #tally, #zip

Constructor Details

#initialize(size = 0, obj = nil, &block) ⇒ Array

Private method for Array creation.

ISO 15.2.12.5.15

Raises:


68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'mrblib/array.rb', line 68

def initialize(size=0, obj=nil, &block)
  size = size.__to_int
  raise ArgumentError, "negative array size" if size < 0

  self.clear
  if size > 0
    self[size - 1] = nil # allocate

    idx = 0
    while idx < size
      self[idx] = (block)? block.call(idx): obj
      idx += 1
    end
  end

  self
end

Instance Method Details

#&(elem) ⇒ Object

call-seq: ary & other_ary -> new_ary

Set Intersection—Returns a new array containing elements common to the two arrays, with no duplicates.

[ 1, 1, 3, 5 ] & [ 1, 2, 3 ] #=> [ 1, 3 ]

Raises:


152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 152

def &(elem)
  raise TypeError, "can't convert #{elem.class} into Array" unless elem.class == Array

  hash = {}
  array = []
  idx = 0
  len = elem.size
  while idx < len
    hash[elem[idx]] = true
    idx += 1
  end
  idx = 0
  len = size
  while idx < len
    v = self[idx]
    if hash[v]
      array << v
      hash.delete v
    end
    idx += 1
  end
  array
end

#*Object

15.2.12.5.2


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
# File 'src/array.c', line 424

static mrb_value
mrb_ary_times(mrb_state *mrb, mrb_value self)
{
  struct RArray *a1 = mrb_ary_ptr(self);
  struct RArray *a2;
  mrb_value *ptr;
  mrb_int times, len1;

  mrb_get_args(mrb, "i", &times);
  if (times < 0) {
    mrb_raise(mrb, E_ARGUMENT_ERROR, "negative argument");
  }
  if (times == 0) return mrb_ary_new(mrb);
  if (ARY_MAX_SIZE / times < ARY_LEN(a1)) {
    mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
  }
  len1 = ARY_LEN(a1);
  a2 = ary_new_capa(mrb, len1 * times);
  ARY_SET_LEN(a2, len1 * times);
  ptr = ARY_PTR(a2);
  while (times--) {
    array_copy(ptr, ARY_PTR(a1), len1);
    ptr += len1;
  }

  return mrb_obj_value(a2);
}

#+Object

15.2.12.5.1


338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
# File 'src/array.c', line 338

static mrb_value
mrb_ary_plus(mrb_state *mrb, mrb_value self)
{
  struct RArray *a1 = mrb_ary_ptr(self);
  struct RArray *a2;
  mrb_value *ptr;
  mrb_int blen, len1;

  mrb_get_args(mrb, "a", &ptr, &blen);
  if (ARY_MAX_SIZE - blen < ARY_LEN(a1)) {
    mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
  }
  len1 = ARY_LEN(a1);
  a2 = ary_new_capa(mrb, len1 + blen);
  array_copy(ARY_PTR(a2), ARY_PTR(a1), len1);
  array_copy(ARY_PTR(a2) + len1, ptr, blen);
  ARY_SET_LEN(a2, len1+blen);

  return mrb_obj_value(a2);
}

#-(elem) ⇒ Object

call-seq: ary - other_ary -> new_ary

Array Difference—Returns a new array that is a copy of the original array, removing any items that also appear in other_ary. (If you need set-like behavior, see the library class Set.)

[ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ] #=> [ 3, 3, 5 ]

Raises:


70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 70

def -(elem)
  raise TypeError, "can't convert #{elem.class} into Array" unless elem.class == Array

  hash = {}
  array = []
  idx = 0
  len = elem.size
  while idx < len
    hash[elem[idx]] = true
    idx += 1
  end
  idx = 0
  len = size
  while idx < len
    v = self[idx]
    array << v unless hash[v]
    idx += 1
  end
  array
end

#<<Object

15.2.12.5.3


508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
# File 'src/array.c', line 508

static mrb_value
mrb_ary_push_m(mrb_state *mrb, mrb_value self)
{
  mrb_value *argv;
  mrb_int len, len2, alen;
  struct RArray *a;

  mrb_get_args(mrb, "*!", &argv, &alen);
  a = mrb_ary_ptr(self);
  ary_modify(mrb, a);
  len = ARY_LEN(a);
  len2 = len + alen;
  if (ARY_CAPA(a) < len2) {
    ary_expand_capa(mrb, a, len2);
  }
  array_copy(ARY_PTR(a)+len, argv, alen);
  ARY_SET_LEN(a, len2);
  mrb_write_barrier(mrb, (struct RBasic*)a);

  return self;
}

#<=>(other) ⇒ Object

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 value of the corresponding element in the other array.

ISO 15.2.12.5.36 (x)


158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'mrblib/array.rb', line 158

def <=>(other)
  other = self.__ary_cmp(other)
  return 0 if 0 == other
  return nil if nil == other

  len = self.size
  n = other.size
  len = n if len > n
  i = 0
  while i < len
    n = (self[i] <=> other[i])
    return n if n.nil? || n != 0
    i += 1
  end
  len = self.size - other.size
  if len == 0
    0
  elsif len > 0
    1
  else
    -1
  end
end

#==(other) ⇒ Object

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 the other array.

ISO 15.2.12.5.33 (x)


115
116
117
118
119
120
121
122
123
124
125
126
# File 'mrblib/array.rb', line 115

def ==(other)
  other = self.__ary_eq(other)
  return false if other == false
  return true  if other == true
  len = self.size
  i = 0
  while i < len
    return false if self[i] != other[i]
    i += 1
  end
  return true
end

#[](index) ⇒ Object? #[](start, length) ⇒ Array? #[](range) ⇒ Array? #slice(index) ⇒ Object? #slice(start, length) ⇒ Array? #slice(range) ⇒ Array?

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[1] => “b” a[1,2] => [“b”, “c”] a[1..-2] => [“b”, “c”, “d”]

Overloads:

  • #[](index) ⇒ Object?

    Returns:

    • (Object, nil)
  • #[](start, length) ⇒ Array?

    Returns:

  • #[](range) ⇒ Array?

    Returns:

  • #slice(index) ⇒ Object?

    Returns:

    • (Object, nil)
  • #slice(start, length) ⇒ Array?

    Returns:

  • #slice(range) ⇒ Array?

    Returns:


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
# File 'src/array.c', line 852

static mrb_value
mrb_ary_aget(mrb_state *mrb, mrb_value self)
{
  struct RArray *a = mrb_ary_ptr(self);
  mrb_int i, len, alen;
  mrb_value index;

  if (mrb_get_args(mrb, "o|i", &index, &len) == 1) {
    switch (mrb_type(index)) {
      /* a[n..m] */
    case MRB_TT_RANGE:
      if (mrb_range_beg_len(mrb, index, &i, &len, ARY_LEN(a), TRUE) == MRB_RANGE_OK) {
        return ary_subseq(mrb, a, i, len);
      }
      else {
        return mrb_nil_value();
      }
    case MRB_TT_FIXNUM:
      return mrb_ary_ref(mrb, self, mrb_fixnum(index));
    default:
      return mrb_ary_ref(mrb, self, aget_index(mrb, index));
    }
  }

  i = aget_index(mrb, index);
  alen = ARY_LEN(a);
  if (i < 0) i += alen;
  if (i < 0 || alen < i) return mrb_nil_value();
  if (len < 0) return mrb_nil_value();
  if (alen == i) return mrb_ary_new(mrb);
  if (len > alen - i) len = alen - i;

  return ary_subseq(mrb, a, i, len);
}

#[]=(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”]

Overloads:

  • #[]=(index) ⇒ Object

    Returns:

    • (Object)
  • #[]=(start, length) ⇒ Object?

    Returns:

    • (Object, nil)
  • #[]=(range) ⇒ Object?

    Returns:

    • (Object, nil)

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
# File 'src/array.c', line 922

static mrb_value
mrb_ary_aset(mrb_state *mrb, mrb_value self)
{
  mrb_value v1, v2, v3;
  mrb_int i, len;

  mrb_ary_modify(mrb, mrb_ary_ptr(self));
  if (mrb_get_args(mrb, "oo|o", &v1, &v2, &v3) == 2) {
    /* a[n..m] = v */
    switch (mrb_range_beg_len(mrb, v1, &i, &len, RARRAY_LEN(self), FALSE)) {
    case MRB_RANGE_TYPE_MISMATCH:
      mrb_ary_set(mrb, self, aget_index(mrb, v1), v2);
      break;
    case MRB_RANGE_OK:
      mrb_ary_splice(mrb, self, i, len, v2);
      break;
    case MRB_RANGE_OUT:
      mrb_raisef(mrb, E_RANGE_ERROR, "%v out of range", v1);
      break;
    }
    return v2;
  }

  /* a[n,m] = v */
  mrb_ary_splice(mrb, self, aget_index(mrb, v1), aget_index(mrb, v2), v3);
  return v3;
}

#__ary_cmpObject


1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
# File 'src/array.c', line 1232

static mrb_value
mrb_ary_cmp(mrb_state *mrb, mrb_value ary1)
{
  mrb_value ary2;

  mrb_get_args(mrb, "o", &ary2);
  if (mrb_obj_equal(mrb, ary1, ary2)) return mrb_fixnum_value(0);
  if (!mrb_array_p(ary2)) {
    return mrb_nil_value();
  }

  return ary2;
}

#__ary_eqObject

15.2.12.5.30


1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
# File 'src/array.c', line 1217

static mrb_value
mrb_ary_eq(mrb_state *mrb, mrb_value ary1)
{
  mrb_value ary2;

  mrb_get_args(mrb, "o", &ary2);
  if (mrb_obj_equal(mrb, ary1, ary2)) return mrb_true_value();
  if (!mrb_array_p(ary2)) {
    return mrb_false_value();
  }
  if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return mrb_false_value();

  return ary2;
}

#__ary_indexObject

kept for mruby-array-ext


1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
# File 'src/array.c', line 1025

static mrb_value
mrb_ary_index_m(mrb_state *mrb, mrb_value self)
{
  mrb_value obj;
  mrb_int i;

  mrb_get_args(mrb, "o", &obj);
  for (i = 0; i < RARRAY_LEN(self); i++) {
    if (mrb_equal(mrb, RARRAY_PTR(self)[i], obj)) {
      return mrb_fixnum_value(i);
    }
  }
  return mrb_nil_value();
}

#__svalueObject

internal method to convert multi-value to single value


1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
# File 'src/array.c', line 1247

static mrb_value
mrb_ary_svalue(mrb_state *mrb, mrb_value ary)
{
  switch (RARRAY_LEN(ary)) {
  case 0:
    return mrb_nil_value();
  case 1:
    return RARRAY_PTR(ary)[0];
  default:
    return ary;
  }
}

#_inspect(recur_list) ⇒ Object


86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'mrblib/array.rb', line 86

def _inspect(recur_list)
  size = self.size
  return "[]" if size == 0
  return "[...]" if recur_list[self.object_id]
  recur_list[self.object_id] = true
  ary=[]
  i=0
  while i<size
    ary<<self[i]._inspect(recur_list)
    i+=1
  end
  "["+ary.join(", ")+"]"
end

#assoc(obj) ⇒ Array?

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

Returns:


27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'mrbgems/mruby-array-ext/src/array.c', line 27

static mrb_value
mrb_ary_assoc(mrb_state *mrb, mrb_value ary)
{
  mrb_int i;
  mrb_value v, k;

  mrb_get_args(mrb, "o", &k);

  for (i = 0; i < RARRAY_LEN(ary); ++i) {
    v = mrb_check_array_type(mrb, RARRAY_PTR(ary)[i]);
    if (!mrb_nil_p(v) && RARRAY_LEN(v) > 0 &&
        mrb_equal(mrb, RARRAY_PTR(v)[0], k))
      return v;
  }
  return mrb_nil_value();
}

#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”

Returns:

  • (Object, nil)

89
90
91
92
93
94
95
96
# File 'mrbgems/mruby-array-ext/src/array.c', line 89

static mrb_value
mrb_ary_at(mrb_state *mrb, mrb_value ary)
{
  mrb_int pos;
  mrb_get_args(mrb, "i", &pos);

  return mrb_ary_entry(ary, pos);
}

#bsearch(&block) ⇒ Object

call-seq: ary.bsearch {|x| block } -> elem

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[k] if 0 <= k < i,
  • the block returns zero for ary[k] if i <= k < j, and
  • the block returns a negative number for ary[k] 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).truncate } #=> 4 or 7
# try to find v such that 8 <= v < 10
ary.bsearch {|x| 4 - (x / 2).truncate } #=> 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.


632
633
634
635
636
637
638
639
640
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 632

def bsearch(&block)
  return to_enum :bsearch unless block

  if idx = bsearch_index(&block)
    self[idx]
  else
    nil
  end
end

#bsearch_index(&block) ⇒ Object

call-seq: ary.bsearch_index {|x| block } -> int or nil

By using binary search, finds an index of a value from this array which meets the given condition in O(log n) where n is the size of the array.

It supports two modes, depending on the nature of the block and they are exactly the same as in the case of #bsearch method with the only difference being that this method returns the index of the element instead of the element itself. For more details consult the documentation for #bsearch.


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
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 654

def bsearch_index(&block)
  return to_enum :bsearch_index unless block

  low = 0
  high = size
  satisfied = false

  while low < high
    mid = ((low+high)/2).truncate
    res = block.call self[mid]

    case res
    when 0 # find-any mode: Found!
      return mid
    when Numeric # find-any mode: Continue...
      in_lower_half = res < 0
    when true # find-min mode
      in_lower_half = true
      satisfied = true
    when false, nil # find-min mode
      in_lower_half = false
    else
      raise TypeError, 'invalid block result (must be numeric, true, false or nil)'
    end

    if in_lower_half
      high = mid
    else
      low = mid + 1
    end
  end

  satisfied ? low : nil
end

#clearObject

15.2.12.5.6


1105
1106
1107
1108
1109
# File 'src/array.c', line 1105

static mrb_value
mrb_ary_clear_m(mrb_state *mrb, mrb_value self)
{
  return mrb_ary_clear(mrb, self);
}

#collect!(&block) ⇒ Object Also known as: map!

Calls the given block for each element of +self+ and pass the respective element. Each element will be replaced by the resulting values.

ISO 15.2.12.5.7


46
47
48
49
50
51
52
53
54
55
56
# File 'mrblib/array.rb', line 46

def collect!(&block)
  return to_enum :collect! unless block

  idx = 0
  len = size
  while idx < len
    self[idx] = block.call self[idx]
    idx += 1
  end
  self
end

#combination(n, &block) ⇒ Object

call-seq: ary.combination(n) { |c| block } -> ary ary.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


897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 897

def combination(n, &block)
  return to_enum(:combination, n) unless block
  size = self.size
  if n == 0
     yield []
  elsif n == 1
    i = 0
    while i<size
      yield [self[i]]
      i += 1
    end
  elsif n <= size
    i = 0
    while i<size
      result = [self[i]]
      self[i+1..-1].combination(n-1) do |c|
        yield result + c
      end
      i += 1
    end
  end
  self
end

#compactObject

call-seq: ary.compact -> new_ary

Returns a copy of +self+ with all +nil+ elements removed.

[ “a”, nil, “b”, nil, “c”, nil ].compact #=> [ “a”, “b”, “c” ]


265
266
267
268
269
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 265

def compact
  result = self.dup
  result.compact!
  result
end

#compact!Object

call-seq: ary.compact! -> ary or nil

Removes +nil+ elements from the array. Returns +nil+ if no changes were made, otherwise returns ary.

[ “a”, nil, “b”, nil, “c” ].compact! #=> [ “a”, “b”, “c” ] [ “a”, “b”, “c” ].compact! #=> nil


282
283
284
285
286
287
288
289
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 282

def compact!
  result = self.select { |e| !e.nil? }
  if result.size == self.size
    nil
  else
    self.replace(result)
  end
end

#concatObject

15.2.12.5.8


328
329
330
331
332
333
334
335
336
# File 'src/array.c', line 328

static mrb_value
mrb_ary_concat_m(mrb_state *mrb, mrb_value self)
{
  mrb_value ary;

  mrb_get_args(mrb, "A", &ary);
  mrb_ary_concat(mrb, self, ary);
  return self;
}

#delete(key, &block) ⇒ Object

Delete element with index +key+


184
185
186
187
188
189
190
191
# File 'mrblib/array.rb', line 184

def delete(key, &block)
  while i = self.index(key)
    self.delete_at(i)
    ret = key
  end
  return block.call if ret.nil? && block
  ret
end

#delete_atObject

15.2.12.5.9


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
# File 'src/array.c', line 950

static mrb_value
mrb_ary_delete_at(mrb_state *mrb, mrb_value self)
{
  struct RArray *a = mrb_ary_ptr(self);
  mrb_int   index;
  mrb_value val;
  mrb_value *ptr;
  mrb_int len, alen;

  mrb_get_args(mrb, "i", &index);
  alen = ARY_LEN(a);
  if (index < 0) index += alen;
  if (index < 0 || alen <= index) return mrb_nil_value();

  ary_modify(mrb, a);
  ptr = ARY_PTR(a);
  val = ptr[index];

  ptr += index;
  len = alen - index;
  while (--len) {
    *ptr = *(ptr+1);
    ++ptr;
  }
  ARY_SET_LEN(a, alen-1);

  ary_shrink_capa(mrb, a);

  return val;
}

#delete_if(&block) ⇒ Object

call-seq: ary.delete_if { |item| block } -> ary ary.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.

scores = [ 97, 42, 75 ]
scores.delete_if {|score| score < 80 }   #=> [97]

513
514
515
516
517
518
519
520
521
522
523
524
525
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 513

def delete_if(&block)
  return to_enum :delete_if unless block

  idx = 0
  while idx < self.size do
    if block.call(self[idx])
      self.delete_at(idx)
    else
      idx += 1
    end
  end
  self
end

#difference(*args) ⇒ Object

call-seq: ary.difference(other_ary1, other_ary2, …) -> new_ary

Returns a new array that is a copy of the original array, removing all occurrences of any item that also appear in +other_ary+. The order is preserved from the original array.


99
100
101
102
103
104
105
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 99

def difference(*args)
  ary = self
  args.each do |x|
    ary = ary - x
  end
  ary
end

#dig(idx, *args) ⇒ Object

call-seq: ary.dig(idx, …) -> object

Extracts the nested value specified by the sequence of idx objects by calling +dig+ at each step, returning +nil+ if any intermediate step is +nil+.


816
817
818
819
820
821
822
823
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 816

def dig(idx,*args)
  n = self[idx]
  if args.size > 0
    n&.dig(*args)
  else
    n
  end
end

#each_index(&block) ⇒ Object

Calls the given block for each element of +self+ and pass the index of the respective element.

ISO 15.2.12.5.11


29
30
31
32
33
34
35
36
37
38
# File 'mrblib/array.rb', line 29

def each_index(&block)
  return to_enum :each_index unless block

  idx = 0
  while idx < length
    block.call(idx)
    idx += 1
  end
  self
end

#empty?Boolean

15.2.12.5.12

Returns:

  • (Boolean)

1111
1112
1113
1114
1115
1116
1117
# File 'src/array.c', line 1111

static mrb_value
mrb_ary_empty_p(mrb_state *mrb, mrb_value self)
{
  struct RArray *a = mrb_ary_ptr(self);

  return mrb_bool_value(ARY_LEN(a) == 0);
}

#eql?(other) ⇒ Boolean

Returns true if +self+ and other are the same object, or are both arrays with the same content.

ISO 15.2.12.5.34 (x)

Returns:

  • (Boolean)

133
134
135
136
137
138
139
140
141
142
143
144
# File 'mrblib/array.rb', line 133

def eql?(other)
  other = self.__ary_eq(other)
  return false if other == false
  return true  if other == true
  len = self.size
  i = 0
  while i < len
    return false unless self[i].eql?(other[i])
    i += 1
  end
  return true
end

#fetch(n, ifnone = NONE, &block) ⇒ Object

call-seq: ary.fetch(index) -> obj ary.fetch(index, default) -> obj ary.fetch(index) { |index| block } -> obj

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"

327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 327

def fetch(n, ifnone=NONE, &block)
  warn "block supersedes default value argument" if !n.nil? && ifnone != NONE && block

  idx = n
  if idx < 0
    idx += size
  end
  if idx < 0 || size <= idx
    return block.call(n) if block
    if ifnone == NONE
      raise IndexError, "index #{n} outside of array bounds: #{-size}...#{size}"
    end
    return ifnone
  end
  self[idx]
end

#fill(arg0 = nil, arg1 = nil, arg2 = nil, &block) ⇒ Object

call-seq: ary.fill(obj) -> ary ary.fill(obj, start [, length]) -> ary ary.fill(obj, range ) -> ary ary.fill { |index| block } -> ary ary.fill(start [, length] ) { |index| block } -> ary ary.fill(range) { |index| block } -> ary

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("w", -1)          #=> ["x", "x", "x", "w"]
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]
a.fill(1, 2) { |i| i+1 } #=> [0, 2, 3, 27]
a.fill(0..1) { |i| i+1 } #=> [1, 2, 3, 27]

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
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 377

def fill(arg0=nil, arg1=nil, arg2=nil, &block)
  if arg0.nil? && arg1.nil? && arg2.nil? && !block
    raise ArgumentError, "wrong number of arguments (0 for 1..3)"
  end

  beg = len = 0
  ary = []
  if block
    if arg0.nil? && arg1.nil? && arg2.nil?
      # ary.fill { |index| block }                    -> ary
      beg = 0
      len = self.size
    elsif !arg0.nil? && arg0.kind_of?(Range)
      # ary.fill(range) { |index| block }             -> ary
      beg = arg0.begin
      beg += self.size if beg < 0
      len = arg0.end
      len += self.size if len < 0
      len += 1 unless arg0.exclude_end?
    elsif !arg0.nil?
      # ary.fill(start [, length] ) { |index| block } -> ary
      beg = arg0
      beg += self.size if beg < 0
      if arg1.nil?
        len = self.size
      else
        len = arg0 + arg1
      end
    end
  else
    if !arg0.nil? && arg1.nil? && arg2.nil?
      # ary.fill(obj)                                 -> ary
      beg = 0
      len = self.size
    elsif !arg0.nil? && !arg1.nil? && arg1.kind_of?(Range)
      # ary.fill(obj, range )                         -> ary
      beg = arg1.begin
      beg += self.size if beg < 0
      len = arg1.end
      len += self.size if len < 0
      len += 1 unless arg1.exclude_end?
    elsif !arg0.nil? && !arg1.nil?
      # ary.fill(obj, start [, length])               -> ary
      beg = arg1
      beg += self.size if beg < 0
      if arg2.nil?
        len = self.size
      else
        len = beg + arg2
      end
    end
  end

  i = beg
  if block
    while i < len
      self[i] = block.call(i)
      i += 1
    end
  else
    while i < len
      self[i] = arg0
      i += 1
    end
  end
  self
end

#firstObject

15.2.12.5.13


981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
# File 'src/array.c', line 981

static mrb_value
mrb_ary_first(mrb_state *mrb, mrb_value self)
{
  struct RArray *a = mrb_ary_ptr(self);
  mrb_int size, alen;

  if (mrb_get_argc(mrb) == 0) {
    return (ARY_LEN(a) > 0)? ARY_PTR(a)[0]: mrb_nil_value();
  }
  mrb_get_args(mrb, "|i", &size);
  if (size < 0) {
    mrb_raise(mrb, E_ARGUMENT_ERROR, "negative array size");
  }

  alen = ARY_LEN(a);
  if (size > alen) size = alen;
  if (ARY_SHARED_P(a)) {
    return ary_subseq(mrb, a, 0, size);
  }
  return mrb_ary_new_from_values(mrb, size, ARY_PTR(a));
}

#flatten(depth = nil) ⇒ Object

call-seq: ary.flatten -> new_ary ary.flatten(level) -> new_ary

Returns a new array that is a one-dimensional flattening of this array (recursively). That is, for every element that is an array, extract its elements into the new array. If 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]]


211
212
213
214
215
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 211

def flatten(depth=nil)
  res = dup
  res.flatten! depth
  res
end

#flatten!(depth = nil) ⇒ Object

call-seq: ary.flatten! -> ary or nil ary.flatten!(level) -> array or nil

Flattens +self+ in place. Returns nil if no modifications were made (i.e., ary contains no subarrays.) If 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]]


234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 234

def flatten!(depth=nil)
  modified = false
  ar = []
  idx = 0
  len = size
  while idx < len
    e = self[idx]
    if e.is_a?(Array) && (depth.nil? || depth > 0)
      ar += e.flatten(depth.nil? ? nil : depth - 1)
      modified = true
    else
      ar << e
    end
    idx += 1
  end
  if modified
    self.replace(ar)
  else
    nil
  end
end

#index(val = NONE, &block) ⇒ Object

call-seq: ary.index(val) -> int or nil ary.index {|item| block } -> int or nil

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.

ISO 15.2.12.5.14


1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
# File 'src/array.c', line 1025

static mrb_value
mrb_ary_index_m(mrb_state *mrb, mrb_value self)
{
  mrb_value obj;
  mrb_int i;

  mrb_get_args(mrb, "o", &obj);
  for (i = 0; i < RARRAY_LEN(self); i++) {
    if (mrb_equal(mrb, RARRAY_PTR(self)[i], obj)) {
      return mrb_fixnum_value(i);
    }
  }
  return mrb_nil_value();
}

#initialize_copyObject

15.2.12.5.16


413
414
415
416
417
418
419
420
421
422
# File 'src/array.c', line 413

static mrb_value
mrb_ary_replace_m(mrb_state *mrb, mrb_value self)
{
  mrb_value other;

  mrb_get_args(mrb, "A", &other);
  mrb_ary_replace(mrb, self, other);

  return self;
}

#insert(idx, *args) ⇒ Object

call-seq: ary.insert(index, obj…) -> ary

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"]

574
575
576
577
578
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 574

def insert(idx, *args)
  idx += self.size + 1 if idx < 0
  self[idx, 0] = args
  self
end

#inspectObject Also known as: to_s

Return the contents of this array as a string.

ISO 15.2.12.5.31 (x)


103
104
105
# File 'mrblib/array.rb', line 103

def inspect
  self._inspect({})
end

#intersection(*args) ⇒ Object

call-seq: ary.intersection(other_ary,…) -> new_ary

Set Intersection—Returns a new array containing elements common to this array and other_arys, removing duplicates. The order is preserved from the original array.

[1, 2, 3].intersection([3, 4, 1], [1, 3, 5]) #=> [1, 3]


186
187
188
189
190
191
192
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 186

def intersection(*args)
  ary = self
  args.each do |x|
    ary = ary & x
  end
  ary
end

#join(sep = "") ⇒ String

Returns a string created by converting each element of the array to a string, separated by sep.

[ “a”, “b”, “c” ].join #=> “abc” [ “a”, “b”, “c” ].join(“-“) #=> “a-b-c”

Returns:


1208
1209
1210
1211
1212
1213
1214
1215
# File 'src/array.c', line 1208

static mrb_value
mrb_ary_join_m(mrb_state *mrb, mrb_value ary)
{
  mrb_value sep = mrb_nil_value();

  mrb_get_args(mrb, "|S!", &sep);
  return mrb_ary_join(mrb, ary, sep);
}

#keep_if(&block) ⇒ Object

call-seq: ary.keep_if { |item| block } -> ary ary.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 = [1, 2, 3, 4, 5]
a.keep_if { |val| val > 3 } #=> [4, 5]

735
736
737
738
739
740
741
742
743
744
745
746
747
748
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 735

def keep_if(&block)
  return to_enum :keep_if unless block

  idx = 0
  len = self.size
  while idx < self.size do
    if block.call(self[idx])
      idx += 1
    else
      self.delete_at(idx)
    end
  end
  self
end

#lastObject

15.2.12.5.18


1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
# File 'src/array.c', line 1003

static mrb_value
mrb_ary_last(mrb_state *mrb, mrb_value self)
{
  struct RArray *a = mrb_ary_ptr(self);
  mrb_int n, size, alen;

  n = mrb_get_args(mrb, "|i", &size);
  alen = ARY_LEN(a);
  if (n == 0) {
    return (alen > 0) ? ARY_PTR(a)[alen - 1]: mrb_nil_value();
  }

  if (size < 0) {
    mrb_raise(mrb, E_ARGUMENT_ERROR, "negative array size");
  }
  if (size > alen) size = alen;
  if (ARY_SHARED_P(a) || size > ARY_DEFAULT_LEN) {
    return ary_subseq(mrb, a, alen - size, size);
  }
  return mrb_ary_new_from_values(mrb, size, ARY_PTR(a) + alen - size);
}

#lengthObject

15.2.12.5.19


1079
1080
1081
1082
1083
1084
1085
# File 'src/array.c', line 1079

static mrb_value
mrb_ary_size(mrb_state *mrb, mrb_value self)
{
  struct RArray *a = mrb_ary_ptr(self);

  return mrb_fixnum_value(ARY_LEN(a));
}

#permutation(n = self.size, &block) ⇒ Object

call-seq: ary.permutation { |p| block } -> ary ary.permutation -> Enumerator ary.permutation(n) { |p| block } -> ary ary.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


851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 851

def permutation(n=self.size, &block)
  return to_enum(:permutation, n) unless block
  size = self.size
  if n == 0
    yield []
  elsif 0 < n && n <= size
    i = 0
    while i<size
      result = [self[i]]
      if n-1 > 0
        ary = self[0...i] + self[i+1..-1]
        ary.permutation(n-1) do |c|
          yield result + c
        end
      else
        yield result
      end
      i += 1
    end
  end
  self
end

#popObject

15.2.12.5.21


530
531
532
533
534
535
536
537
538
539
540
# File 'src/array.c', line 530

MRB_API mrb_value
mrb_ary_pop(mrb_state *mrb, mrb_value ary)
{
  struct RArray *a = mrb_ary_ptr(ary);
  mrb_int len = ARY_LEN(a);

  ary_modify_check(mrb, a);
  if (len == 0) return mrb_nil_value();
  ARY_SET_LEN(a, len-1);
  return ARY_PTR(a)[len-1];
}

#pushObject Also known as: append

15.2.12.5.22


508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
# File 'src/array.c', line 508

static mrb_value
mrb_ary_push_m(mrb_state *mrb, mrb_value self)
{
  mrb_value *argv;
  mrb_int len, len2, alen;
  struct RArray *a;

  mrb_get_args(mrb, "*!", &argv, &alen);
  a = mrb_ary_ptr(self);
  ary_modify(mrb, a);
  len = ARY_LEN(a);
  len2 = len + alen;
  if (ARY_CAPA(a) < len2) {
    ary_expand_capa(mrb, a, len2);
  }
  array_copy(ARY_PTR(a)+len, argv, alen);
  ARY_SET_LEN(a, len2);
  mrb_write_barrier(mrb, (struct RBasic*)a);

  return self;
}

#rassoc(obj) ⇒ Array?

Searches through the array whose elements are also arrays. Compares obj with the second element of each contained array using ==. Returns the first contained array that matches. See also Array#assoc.

a = [ [ 1, “one”], [2, “two”], [3, “three”], [“ii”, “two”] ] a.rassoc(“two”) #=> [2, “two”] a.rassoc(“four”) #=> nil

Returns:


58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'mrbgems/mruby-array-ext/src/array.c', line 58

static mrb_value
mrb_ary_rassoc(mrb_state *mrb, mrb_value ary)
{
  mrb_int i;
  mrb_value v, value;

  mrb_get_args(mrb, "o", &value);

  for (i = 0; i < RARRAY_LEN(ary); ++i) {
    v = RARRAY_PTR(ary)[i];
    if (mrb_array_p(v) &&
        RARRAY_LEN(v) > 1 &&
        mrb_equal(mrb, RARRAY_PTR(v)[1], value))
      return v;
  }
  return mrb_nil_value();
}

#reject!(&block) ⇒ Object

call-seq: ary.reject! { |item| block } -> ary or nil ary.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.


542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 542

def reject!(&block)
  return to_enum :reject! unless block

  len = self.size
  idx = 0
  while idx < self.size do
    if block.call(self[idx])
      self.delete_at(idx)
    else
      idx += 1
    end
  end
  if self.size == len
    nil
  else
    self
  end
end

#replaceObject

15.2.12.5.23


413
414
415
416
417
418
419
420
421
422
# File 'src/array.c', line 413

static mrb_value
mrb_ary_replace_m(mrb_state *mrb, mrb_value self)
{
  mrb_value other;

  mrb_get_args(mrb, "A", &other);
  mrb_ary_replace(mrb, self, other);

  return self;
}

#reverseObject

15.2.12.5.24


474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
# File 'src/array.c', line 474

static mrb_value
mrb_ary_reverse(mrb_state *mrb, mrb_value self)
{
  struct RArray *a = mrb_ary_ptr(self), *b = ary_new_capa(mrb, ARY_LEN(a));
  mrb_int len = ARY_LEN(a);

  if (len > 0) {
    mrb_value *p1, *p2, *e;

    p1 = ARY_PTR(a);
    e  = p1 + len;
    p2 = ARY_PTR(b) + len - 1;
    while (p1 < e) {
      *p2-- = *p1++;
    }
    ARY_SET_LEN(b, len);
  }
  return mrb_obj_value(b);
}

#reverse!Object

15.2.12.5.25


452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
# File 'src/array.c', line 452

static mrb_value
mrb_ary_reverse_bang(mrb_state *mrb, mrb_value self)
{
  struct RArray *a = mrb_ary_ptr(self);
  mrb_int len = ARY_LEN(a);

  if (len > 1) {
    mrb_value *p1, *p2;

    ary_modify(mrb, a);
    p1 = ARY_PTR(a);
    p2 = p1 + len - 1;

    while (p1 < p2) {
      mrb_value tmp = *p1;
      *p1++ = *p2;
      *p2-- = tmp;
    }
  }
  return self;
}

#reverse_each(&block) ⇒ Object

for efficiency


292
293
294
295
296
297
298
299
300
301
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 292

def reverse_each(&block)
  return to_enum :reverse_each unless block

  i = self.size - 1
  while i>=0
    block.call(self[i])
    i -= 1
  end
  self
end

#rindexObject

15.2.12.5.26


1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
# File 'src/array.c', line 1040

static mrb_value
mrb_ary_rindex_m(mrb_state *mrb, mrb_value self)
{
  mrb_value obj;
  mrb_int i, len;

  mrb_get_args(mrb, "o", &obj);
  for (i = RARRAY_LEN(self) - 1; i >= 0; i--) {
    if (mrb_equal(mrb, RARRAY_PTR(self)[i], obj)) {
      return mrb_fixnum_value(i);
    }
    if (i > (len = RARRAY_LEN(self))) {
      i = len;
    }
  }
  return mrb_nil_value();
}

#rotate(count = 1) ⇒ Object

call-seq: ary.rotate(count=1) -> new_ary

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"]

461
462
463
464
465
466
467
468
469
470
471
472
473
474
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 461

def rotate(count=1)
  ary = []
  len = self.length

  if len > 0
    idx = (count < 0) ? (len - (~count % len) - 1) : (count % len) # rotate count
    len.times do
      ary << self[idx]
      idx += 1
      idx = 0 if idx > len-1
    end
  end
  ary
end

#rotate!(count = 1) ⇒ Object

call-seq: ary.rotate!(count=1) -> ary

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"]

492
493
494
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 492

def rotate!(count=1)
  self.replace(self.rotate(count))
end

#select!(&block) ⇒ Object Also known as: filter!

call-seq: ary.select! {|item| block } -> ary or nil ary.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.


764
765
766
767
768
769
770
771
772
773
774
775
776
777
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 764

def select!(&block)
  return to_enum :select! unless block

  result = []
  idx = 0
  len = size
  while idx < len
    elem = self[idx]
    result << elem if block.call(elem)
    idx += 1
  end
  return nil if len == result.size
  self.replace(result)
end

#shiftObject

15.2.12.5.27


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
# File 'src/array.c', line 544

MRB_API mrb_value
mrb_ary_shift(mrb_state *mrb, mrb_value self)
{
  struct RArray *a = mrb_ary_ptr(self);
  mrb_int len = ARY_LEN(a);
  mrb_value val;

  ary_modify_check(mrb, a);
  if (len == 0) return mrb_nil_value();
  if (ARY_SHARED_P(a)) {
  L_SHIFT:
    val = a->as.heap.ptr[0];
    a->as.heap.ptr++;
    a->as.heap.len--;
    return val;
  }
  if (len > ARY_SHIFT_SHARED_MIN) {
    ary_make_shared(mrb, a);
    goto L_SHIFT;
  }
  else {
    mrb_value *ptr = ARY_PTR(a);
    mrb_int size = len;

    val = *ptr;
    while (--size) {
      *ptr = *(ptr+1);
      ++ptr;
    }
    ARY_SET_LEN(a, len-1);
  }
  return val;
}

#sizeObject

15.2.12.5.28


1079
1080
1081
1082
1083
1084
1085
# File 'src/array.c', line 1079

static mrb_value
mrb_ary_size(mrb_state *mrb, mrb_value self)
{
  struct RArray *a = mrb_ary_ptr(self);

  return mrb_fixnum_value(ARY_LEN(a));
}

#[](index) ⇒ Object? #[](start, length) ⇒ Array? #[](range) ⇒ Array? #slice(index) ⇒ Object? #slice(start, length) ⇒ Array? #slice(range) ⇒ Array?

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[1] => “b” a[1,2] => [“b”, “c”] a[1..-2] => [“b”, “c”, “d”]

Overloads:

  • #[](index) ⇒ Object?

    Returns:

    • (Object, nil)
  • #[](start, length) ⇒ Array?

    Returns:

  • #[](range) ⇒ Array?

    Returns:

  • #slice(index) ⇒ Object?

    Returns:

    • (Object, nil)
  • #slice(start, length) ⇒ Array?

    Returns:

  • #slice(range) ⇒ Array?

    Returns:


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
# File 'src/array.c', line 852

static mrb_value
mrb_ary_aget(mrb_state *mrb, mrb_value self)
{
  struct RArray *a = mrb_ary_ptr(self);
  mrb_int i, len, alen;
  mrb_value index;

  if (mrb_get_args(mrb, "o|i", &index, &len) == 1) {
    switch (mrb_type(index)) {
      /* a[n..m] */
    case MRB_TT_RANGE:
      if (mrb_range_beg_len(mrb, index, &i, &len, ARY_LEN(a), TRUE) == MRB_RANGE_OK) {
        return ary_subseq(mrb, a, i, len);
      }
      else {
        return mrb_nil_value();
      }
    case MRB_TT_FIXNUM:
      return mrb_ary_ref(mrb, self, mrb_fixnum(index));
    default:
      return mrb_ary_ref(mrb, self, aget_index(mrb, index));
    }
  }

  i = aget_index(mrb, index);
  alen = ARY_LEN(a);
  if (i < 0) i += alen;
  if (i < 0 || alen < i) return mrb_nil_value();
  if (len < 0) return mrb_nil_value();
  if (alen == i) return mrb_ary_new(mrb);
  if (len > alen - i) len = alen - i;

  return ary_subseq(mrb, a, i, len);
}

#slice!(index) ⇒ Object? #slice!(start, length) ⇒ Array? #slice!(range) ⇒ Array?

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”]

Overloads:

  • #slice!(index) ⇒ Object?

    Returns:

    • (Object, nil)
  • #slice!(start, length) ⇒ Array?

    Returns:

  • #slice!(range) ⇒ Array?

    Returns:


131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'mrbgems/mruby-array-ext/src/array.c', line 131

static mrb_value
mrb_ary_slice_bang(mrb_state *mrb, mrb_value self)
{
  struct RArray *a = mrb_ary_ptr(self);
  mrb_int i, j, k, len, alen;
  mrb_value val;
  mrb_value *ptr;
  mrb_value ary;

  mrb_ary_modify(mrb, a);

  if (mrb_get_argc(mrb) == 1) {
    mrb_value index;

    mrb_get_args(mrb, "o|i", &index, &len);
    switch (mrb_type(index)) {
    case MRB_TT_RANGE:
      if (mrb_range_beg_len(mrb, index, &i, &len, ARY_LEN(a), TRUE) == MRB_RANGE_OK) {
        goto delete_pos_len;
      }
      else {
        return mrb_nil_value();
      }
    case MRB_TT_FIXNUM:
      val = mrb_funcall(mrb, self, "delete_at", 1, index);
      return val;
    default:
      val = mrb_funcall(mrb, self, "delete_at", 1, index);
      return val;
    }
  }

  mrb_get_args(mrb, "ii", &i, &len);
 delete_pos_len:
  alen = ARY_LEN(a);
  if (i < 0) i += alen;
  if (i < 0 || alen < i) return mrb_nil_value();
  if (len < 0) return mrb_nil_value();
  if (alen == i) return mrb_ary_new(mrb);
  if (len > alen - i) len = alen - i;

  ary = mrb_ary_new_capa(mrb, len);
  ptr = ARY_PTR(a);
  for (j = i, k = 0; k < len; ++j, ++k) {
    mrb_ary_push(mrb, ary, ptr[j]);
  }

  ptr += i;
  for (j = i; j < alen - len; ++j) {
    *ptr = *(ptr+len);
    ++ptr;
  }

  mrb_ary_resize(mrb, self, alen - len);
  return ary;
}

#sort(&block) ⇒ Object


268
269
270
# File 'mrblib/array.rb', line 268

def sort(&block)
  self.dup.sort!(&block)
end

#sort!(&block) ⇒ Object

Sort all elements and replace +self+ with these elements.


203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# File 'mrblib/array.rb', line 203

def sort!(&block)
  stack = [ [ 0, self.size - 1 ] ]
  until stack.empty?
    left, mid, right = stack.pop
    if right == nil
      right = mid
      # sort self[left..right]
      if left < right
        if left + 1 == right
          lval = self[left]
          rval = self[right]
          cmp = if block then block.call(lval,rval) else lval <=> rval end
          if cmp.nil?
            raise ArgumentError, "comparison of #{lval.inspect} and #{rval.inspect} failed"
          end
          if cmp > 0
            self[left]  = rval
            self[right] = lval
          end
        else
          mid = ((left + right + 1) / 2).floor
          stack.push [ left, mid, right ]
          stack.push [ mid, right ]
          stack.push [ left, (mid - 1) ] if left < mid - 1
        end
      end
    else
      lary = self[left, mid - left]
      lsize = lary.size

      # The entity sharing between lary and self may cause a large memory
      # copy operation in the merge loop below.  This harmless operation
      # cancels the sharing and provides a huge performance gain.
      lary[0] = lary[0]

      # merge
      lidx = 0
      ridx = mid
      (left..right).each { |i|
        if lidx >= lsize
          break
        elsif ridx > right
          self[i, lsize - lidx] = lary[lidx, lsize - lidx]
          break
        else
          lval = lary[lidx]
          rval = self[ridx]
          cmp = if block then block.call(lval,rval) else lval <=> rval end
          if cmp.nil?
            raise ArgumentError, "comparison of #{lval.inspect} and #{rval.inspect} failed"
          end
          if cmp <= 0
            self[i] = lval
            lidx += 1
          else
            self[i] = rval
            ridx += 1
          end
        end
      }
    end
  end
  self
end

#to_h(&blk) ⇒ Object

call-seq: ary.to_h -> Hash ary.to_h{|item| … } -> Hash

Returns the result of interpreting aray as an array of [key, value] pairs. If a block is given, it should return [key, value] pairs to construct a hash.

[[:foo, :bar], [1, 2]].to_h
  # => {:foo => :bar, 1 => 2}
[1, 2].to_h{|x| [x, x*2]}
  # => {1 => 2, 2 => 4}

963
964
965
966
967
968
969
970
971
972
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 963

def to_h(&blk)
  h = {}
  self.each do |v|
    v = blk.call(v) if blk
    raise TypeError, "wrong element type #{v.class}" unless Array === v
    raise ArgumentError, "wrong array length (expected 2, was #{v.length})" unless v.length == 2
    h[v[0]] = v[1]
  end
  h
end

#transposeObject

call-seq: ary.transpose -> new_ary

Assumes that self is an array of arrays and transposes the rows and columns.

If the length of the subarrays don’t match, an IndexError is raised.

Examples:

a = [[1,2], [3,4], [5,6]] a.transpose #=> [[1, 3, 5], [2, 4, 6]]


934
935
936
937
938
939
940
941
942
943
944
945
946
947
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 934

def transpose
  return [] if empty?

  column_count = nil
  self.each do |row|
    raise TypeError unless row.is_a?(Array)
    column_count ||= row.size
    raise IndexError, 'element size differs' unless column_count == row.size
  end

  Array.new(column_count) do |column_index|
    self.map { |row| row[column_index] }
  end
end

#union(*args) ⇒ Object

call-seq: ary.union(other_ary,…) -> new_ary

Set Union—Returns a new array by joining this array with other_ary, removing duplicates.

[“a”, “b”, “c”].union([“c”, “d”, “a”], [“a”, “c”, “e”]) #=> [“a”, “b”, “c”, “d”, “e”]


134
135
136
137
138
139
140
141
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 134

def union(*args)
  ary = self.dup
  args.each do |x|
    ary.concat(x)
    ary.uniq!
  end
  ary
end

#uniq(&block) ⇒ Object

call-seq: ary.uniq -> new_ary ary.uniq { |item| … } -> new_ary

Returns a new array by removing duplicate values in +self+.

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”]]


53
54
55
56
57
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 53

def uniq(&block)
  ary = self.dup
  ary.uniq!(&block)
  ary
end

#uniq!(&block) ⇒ Object

call-seq: ary.uniq! -> ary or nil ary.uniq! { |item| … } -> ary or nil

Removes duplicate elements from +self+. 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”]]


18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 18

def uniq!(&block)
  hash = {}
  if block
    self.each do |val|
      key = block.call(val)
      hash[key] = val unless hash.key?(key)
    end
    result = hash.values
  else
    hash = {}
    self.each do |val|
      hash[val] = val
    end
    result = hash.keys
  end
  if result.size == self.size
    nil
  else
    self.replace(result)
  end
end

#unshiftObject Also known as: prepend

15.2.12.5.30


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
# File 'src/array.c', line 610

static mrb_value
mrb_ary_unshift_m(mrb_state *mrb, mrb_value self)
{
  struct RArray *a = mrb_ary_ptr(self);
  mrb_value *vals, *ptr;
  mrb_int alen, len;

  mrb_get_args(mrb, "*!", &vals, &alen);
  if (alen == 0) {
    ary_modify_check(mrb, a);
    return self;
  }
  len = ARY_LEN(a);
  if (alen > ARY_MAX_SIZE - len) {
    mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
  }
  if (ARY_SHARED_P(a)
      && a->as.heap.aux.shared->refcnt == 1 /* shared only referenced from this array */
      && a->as.heap.ptr - a->as.heap.aux.shared->ptr >= alen) /* there's room for unshifted item */ {
    ary_modify_check(mrb, a);
    a->as.heap.ptr -= alen;
    ptr = a->as.heap.ptr;
  }
  else {
    ary_modify(mrb, a);
    if (ARY_CAPA(a) < len + alen)
      ary_expand_capa(mrb, a, len + alen);
    ptr = ARY_PTR(a);
    value_move(ptr + alen, ptr, len);
  }
  array_copy(ptr, vals, alen);
  ARY_SET_LEN(a, len+alen);
  while (alen--) {
    mrb_field_write_barrier_value(mrb, (struct RBasic*)a, vals[alen]);
  }

  return self;
}

#values_atObject


98
99
100
101
102
103
104
105
106
107
# File 'mrbgems/mruby-array-ext/src/array.c', line 98

static mrb_value
mrb_ary_values_at(mrb_state *mrb, mrb_value self)
{
  mrb_int argc;
  mrb_value *argv;

  mrb_get_args(mrb, "*", &argv, &argc);

  return mrb_get_values_at(mrb, self, RARRAY_LEN(self), argc, argv, mrb_ary_ref);
}

#|(elem) ⇒ Object

call-seq: ary | other_ary -> new_ary

Set Union—Returns a new array by joining this array with other_ary, removing duplicates.

[ “a”, “b”, “c” ] | [ “c”, “d”, “a” ] #=> [ “a”, “b”, “c”, “d” ]

Raises:


117
118
119
120
121
122
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 117

def |(elem)
  raise TypeError, "can't convert #{elem.class} into Array" unless elem.class == Array

  ary = self + elem
  ary.uniq! or ary
end