Class: Array

Inherits:
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

NONE =
Object.new

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Enumerable

#all?, #any?, #collect, #count, #cycle, #detect, #drop, #drop_while, #each_cons, #each_slice, #each_with_index, #each_with_object, #entries, #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, to_h, #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)
  raise TypeError, "expected Integer for 1st argument" unless size.kind_of? Integer
  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

Class Method Details

.try_convert(obj) ⇒ Object

call-seq: Array.try_convert(obj) -> array or nil

Tries to convert +obj+ into an array, using +to_ary+ method. 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


19
20
21
22
23
24
25
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 19

def self.try_convert(obj)
  if obj.respond_to?(:to_ary)
    obj.to_ary
  else
    nil
  end
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:


146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 146

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


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

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:


99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 99

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


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

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)


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

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)


110
111
112
113
114
115
116
117
118
119
120
121
# File 'mrblib/array.rb', line 110

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:


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

static mrb_value
mrb_ary_aget(mrb_state *mrb, mrb_value self)
{
  struct RArray *a = mrb_ary_ptr(self);
  mrb_int i, len, alen = ARY_LEN(a);
  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, alen, TRUE) == 1) {
        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);
  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:


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

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 0:                   /* not range */
      mrb_ary_set(mrb, self, aget_index(mrb, v1), v2);
      break;
    case 1:                   /* range */
      mrb_ary_splice(mrb, self, i, len, v2);
      break;
    case 2:                   /* out of range */
      mrb_raisef(mrb, E_RANGE_ERROR, "%S 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


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

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


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

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


1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
# File 'src/array.c', line 1016

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();
}

#__sort_sub__(left, right, &block) ⇒ Object

Quick sort left : the beginning of sort region right : the end of sort region


199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
# File 'mrblib/array.rb', line 199

def __sort_sub__(left, right, &block)
  if left < right
    i = left
    j = right
    pivot = self[i + (j - i) / 2]
    while true
      while ((block)? block.call(self[i], pivot): (self[i] <=> pivot)) < 0
        i += 1
      end
      while ((block)? block.call(pivot, self[j]): (pivot <=> self[j])) < 0
        j -= 1
      end
      break if (i >= j)
      tmp = self[i]; self[i] = self[j]; self[j] = tmp;
      i += 1
      j -= 1
    end
    __sort_sub__(left, i-1, &block)
    __sort_sub__(j+1, right, &block)
  end
end

#__svalueObject

internal method to convert multi-value to single value


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

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

#_inspectObject


86
87
88
89
# File 'mrblib/array.rb', line 86

def _inspect
  return "[]" if self.size == 0
  "["+self.map{|x|x.inspect}.join(", ")+"]"
end

#appendObject

15.2.12.5.22


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

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;
}

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


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.


609
610
611
612
613
614
615
616
617
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 609

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.


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

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


1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
# File 'src/array.c', line 1089

MRB_API mrb_value
mrb_ary_clear(mrb_state *mrb, mrb_value self)
{
  struct RArray *a = mrb_ary_ptr(self);

  ary_modify(mrb, a);
  if (ARY_SHARED_P(a)) {
    mrb_ary_decref(mrb, a->as.heap.aux.shared);
    ARY_UNSET_SHARED_FLAG(a);
  }
  else if (!ARY_EMBED_P(a)){
    mrb_free(mrb, a->as.heap.ptr);
  }
  ARY_SET_EMBED_LEN(a, 0);

  return 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


884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 884

def combination(n, &block)
  size = self.size
  return to_enum(:combination, n) unless block
  return if n > size
  if n == 0
     yield []
  elsif n == 1
    i = 0
    while i<size
      yield [self[i]]
      i += 1
    end
  else
    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
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” ]


241
242
243
244
245
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 241

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


258
259
260
261
262
263
264
265
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 258

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+


179
180
181
182
183
184
185
186
# File 'mrblib/array.rb', line 179

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


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

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 = ARY_LEN(a);

  mrb_get_args(mrb, "i", &index);
  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]

490
491
492
493
494
495
496
497
498
499
500
501
502
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 490

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

#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+.


803
804
805
806
807
808
809
810
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 803

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

#each(&block) ⇒ Object

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

ISO 15.2.12.5.10


13
14
15
16
17
18
19
20
21
22
# File 'mrblib/array.rb', line 13

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

  idx = 0
  while idx < length
    block.call(self[idx])
    idx += 1
  end
  self
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)

1107
1108
1109
1110
1111
1112
1113
# File 'src/array.c', line 1107

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)

128
129
130
131
132
133
134
135
136
137
138
139
# File 'mrblib/array.rb', line 128

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 = nil, 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"

304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 304

def fetch(n=nil, 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]

354
355
356
357
358
359
360
361
362
363
364
365
366
367
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
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 354

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


976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
# File 'src/array.c', line 976

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

  if (mrb_get_argc(mrb) == 0) {
    return (alen > 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");
  }

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


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

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


210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 210

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


1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
# File 'src/array.c', line 1016

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


410
411
412
413
414
415
416
417
418
419
# File 'src/array.c', line 410

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

551
552
553
554
555
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 551

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)


94
95
96
97
98
99
100
# File 'mrblib/array.rb', line 94

def inspect
  begin
    self._inspect
  rescue SystemStackError
    "[...]"
  end
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:


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

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]

712
713
714
715
716
717
718
719
720
721
722
723
724
725
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 712

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


997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
# File 'src/array.c', line 997

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

  if (mrb_get_args(mrb, "|i", &size) == 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


1081
1082
1083
1084
1085
1086
1087
# File 'src/array.c', line 1081

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


838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 838

def permutation(n=self.size, &block)
  size = self.size
  return to_enum(:permutation, n) unless block
  return if n > size
  if n == 0
     yield []
  else
    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
end

#popObject

15.2.12.5.21


527
528
529
530
531
532
533
534
535
536
537
# File 'src/array.c', line 527

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];
}

#prependObject

15.2.12.5.30


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

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;
}

#pushObject

15.2.12.5.22


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

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_type(v) == MRB_TT_ARRAY &&
        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.


519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 519

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


410
411
412
413
414
415
416
417
418
419
# File 'src/array.c', line 410

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


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

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


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

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


268
269
270
271
272
273
274
275
276
277
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 268

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


1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
# File 'src/array.c', line 1031

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

438
439
440
441
442
443
444
445
446
447
448
449
450
451
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 438

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

469
470
471
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 469

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

#select!(&block) ⇒ Object

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.


741
742
743
744
745
746
747
748
749
750
751
752
753
754
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 741

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


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

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


1081
1082
1083
1084
1085
1086
1087
# File 'src/array.c', line 1081

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:


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

static mrb_value
mrb_ary_aget(mrb_state *mrb, mrb_value self)
{
  struct RArray *a = mrb_ary_ptr(self);
  mrb_int i, len, alen = ARY_LEN(a);
  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, alen, TRUE) == 1) {
        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);
  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:


174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
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
# File 'mrbgems/mruby-array-ext/src/array.c', line 174

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 = ARY_LEN(a);
  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, alen, TRUE) == 1) {
        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:
  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


233
234
235
# File 'mrblib/array.rb', line 233

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

#sort!(&block) ⇒ Object

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


225
226
227
228
229
230
231
# File 'mrblib/array.rb', line 225

def sort!(&block)
  size = self.size
  if size > 1
    __sort_sub__(0, size - 1, &block)
  end
  self
end

#to_aryObject

call-seq: ary.to_ary -> ary

Returns +self+.


791
792
793
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 791

def to_ary
  self
end

#to_hHash

Returns the result of interpreting aray as an array of [key, value] paris.

[[:foo, :bar], [1, 2]].to_h
  # => {:foo => :bar, 1 => 2}

Returns:


121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'mrbgems/mruby-array-ext/src/array.c', line 121

static mrb_value
mrb_ary_to_h(mrb_state *mrb, mrb_value ary)
{
  mrb_int i;
  mrb_value v, hash;

  hash = mrb_hash_new_capa(mrb, 0);

  for (i = 0; i < RARRAY_LEN(ary); ++i) {
    mrb_value elt = RARRAY_PTR(ary)[i];
    v = mrb_check_array_type(mrb, elt);

    if (mrb_nil_p(v)) {
      mrb_raisef(mrb, E_TYPE_ERROR, "wrong element type %S at %S (expected array)",
                 mrb_str_new_cstr(mrb,  mrb_obj_classname(mrb, elt)),
                 mrb_fixnum_value(i)
      );
    }

    if (RARRAY_LEN(v) != 2) {
      mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong array length at %S (expected 2, was %S)",
                 mrb_fixnum_value(i),
                 mrb_fixnum_value(RARRAY_LEN(v))
      );
    }

    mrb_hash_set(mrb, hash, RARRAY_PTR(v)[0], RARRAY_PTR(v)[1]);
  }

  return hash;
}

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


921
922
923
924
925
926
927
928
929
930
931
932
933
934
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 921

def transpose
  return [] if empty?

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

  Array.new(column_count) do |column_index|
    self.map { |row| row[column_index] }
  end
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”]]


82
83
84
85
86
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 82

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


43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 43

def uniq!(&block)
  ary = self.dup
  result = []
  if block
    hash = {}
    while ary.size > 0
      val = ary.shift
      key = block.call(val)
      hash[key] = val unless hash.has_key?(key)
    end
    hash.each_value do |value|
      result << value
    end
  else
    while ary.size > 0
      result << ary.shift
      ary.delete(result.last)
    end
  end
  if result.size == self.size
    nil
  else
    self.replace(result)
  end
end

#unshiftObject

15.2.12.5.30


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

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:


130
131
132
133
134
135
# File 'mrbgems/mruby-array-ext/mrblib/array.rb', line 130

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

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