mrbgems/mruby-enum-ext/README.md
This mrbgem extends the Enumerable module in mruby with additional useful methods.
Below is a list of methods added to the Enumerable module, along with a brief description and example for each.
drop(n)Drops the first n elements from an enumerable and returns the rest of the elements in an array.
Example:
a = [1, 2, 3, 4, 5, 0]
a.drop(3) #=> [4, 5, 0]
drop_while { |obj| block }Drops elements up to, but not including, the first element for which the block returns nil or false. Returns an array containing the remaining elements. If no block is given, an enumerator is returned.
Example:
a = [1, 2, 3, 4, 5, 0]
a.drop_while {|i| i < 3 } #=> [3, 4, 5, 0]
take(n)Returns the first n elements from an enumerable as an array.
Example:
a = [1, 2, 3, 4, 5, 0]
a.take(3) #=> [1, 2, 3]
take_while { |obj| block }Passes elements to the block until the block returns nil or false, then stops iterating and returns an array of all prior elements. If no block is given, an enumerator is returned.
Example:
a = [1, 2, 3, 4, 5, 0]
a.take_while {|i| i < 3 } #=> [1, 2]
each_cons(n) { |a| block }Iterates the given block for each array of consecutive n elements. If no block is given, an enumerator is returned.
Example:
(1..10).each_cons(3) {|a| p a}
# outputs below
# [1, 2, 3]
# [2, 3, 4]
# [3, 4, 5]
# [4, 5, 6]
# [5, 6, 7]
# [6, 7, 8]
# [7, 8, 9]
# [8, 9, 10]
each_slice(n) { |a| block }Iterates the given block for each slice of n elements. If no block is given, an enumerator is returned.
Example:
(1..10).each_slice(3) {|a| p a}
# outputs below
# [1, 2, 3]
# [4, 5, 6]
# [7, 8, 9]
# [10]
group_by { |obj| block }Groups the collection by the result of the block. Returns a hash where keys are the evaluated result from the block and values are arrays of elements corresponding to the key. If no block is given, an enumerator is returned.
Example:
(1..6).group_by {|i| i%3} #=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]}
sort_by { |obj| block }Sorts the enumerable using a set of keys generated by mapping the values in the enumerable through the given block. Returns an array. If no block is given, an enumerator is returned. (Note: Array#sort_by and Array#sort_by! are also implemented for optimized in-place sorting for arrays).
Example:
%w(apple pear fig).sort_by { |word| word.length }
#=> ["fig", "pear", "apple"]
(Example adapted, original was for Array#sort_by)
first / first(n)Returns the first element, or the first n elements, of the enumerable. If the enumerable is empty, first returns nil, and first(n) returns an empty array.
Examples:
a = [1, 2, 3, 4, 5]
a.first #=> 1
a.first(3) #=> [1, 2, 3]
[].first #=> nil
[].first(3) #=> []
count / count(item) / count { |obj| block }Returns the number of items in the enumerable.
item is given, counts items equal to item.Examples:
[1, 2, 3, 2].count #=> 4
[1, 2, 3, 2].count(2) #=> 2
[1, 2, 3, 4].count { |x| x%2 == 0 } #=> 2
flat_map { |obj| block } (alias: collect_concat)Returns a new array with the concatenated results of running the block once for every element. If no block is given, an enumerator is returned.
Example:
[1, 2, 3, 4].flat_map { |e| [e, -e] } #=> [1, -1, 2, -2, 3, -3, 4, -4]
[[1, 2], [3, 4]].flat_map { |e| e + [100] } #=> [1, 2, 100, 3, 4, 100]
max_by { |obj| block }Returns the object in the enumerable that gives the maximum value from the given block. If no block is given, an enumerator is returned.
Example:
%w[albatross dog horse].max_by {|x| x.length } #=> "albatross"
min_by { |obj| block }Returns the object in the enumerable that gives the minimum value from the given block. If no block is given, an enumerator is returned.
Example:
%w[albatross dog horse].min_by {|x| x.length } #=> "dog"
minmax / minmax { |a, b| block }Returns a two-element array containing the minimum and maximum values. The first form assumes objects implement Comparable; the second uses the block to return a <=> b.
Examples:
a = %w(albatross dog horse)
a.minmax #=> ["albatross", "horse"]
a.minmax { |a, b| a.length <=> b.length } #=> ["dog", "albatross"]
minmax_by { |obj| block }Returns a two-element array containing the objects that correspond to the minimum and maximum values from the given block. If no block is given, an enumerator is returned.
Example:
%w(albatross dog horse).minmax_by { |x| x.length } #=> ["dog", "albatross"]
none? / none? { |obj| block } / none?(pattern)true if the block never returns true for any element.true if pattern === element is never true for any element.true if none of the collection members are truthy.Examples:
%w(ant bear cat).none? { |word| word.length == 5 } #=> true
%w(ant bear cat).none? { |word| word.length >= 4 } #=> false
%w{ant bear cat}.none?(/d/) #=> true
[1, 3.14, 42].none?(Float) #=> false
[].none? #=> true
[nil, false].none? #=> true
one? / one? { |obj| block } / one?(pattern)true if the block returns true exactly once.true if pattern === element is true for exactly one element.true if exactly one of the collection members is truthy.Examples:
%w(ant bear cat).one? { |word| word.length == 4 } #=> true
%w(ant bear cat).one? { |word| word.length > 4 } #=> false
%w{ant bear cat}.one?(/t/) #=> false # (Note: original example might be specific to mruby version, "ant" and "cat" contain "t")
[nil, true, false].one? #=> true
[nil, true, 99].one?(Integer) #=> true
all? / all? { |obj| block } / all?(pattern)true if the block never returns false or nil for any element.true if pattern === element is true for every element.true if all collection members are truthy.Examples:
%w[ant bear cat].all? { |word| word.length >= 3 } #=> true
%w[ant bear cat].all? { |word| word.length >= 4 } #=> false
[1, 2i, 3.14].all?(Numeric) #=> true
[nil, true, 99].all? #=> false
any? / any? { |obj| block } / any?(pattern)true if the block ever returns a truthy value for an element.true if pattern === element is true for any element.true if at least one collection member is truthy.Examples:
%w[ant bear cat].any? { |word| word.length >= 3 } #=> true
%w[ant bear cat].any?(/d/) #=> false
[nil, true, 99].any?(Integer) #=> true
[nil, true, 99].any? #=> true
[].any? #=> false
each_with_object(obj) { |(*args), memo_obj| ... }Iterates the given block for each element with an arbitrary object obj given, and returns the initially given obj. If no block is given, an enumerator is returned.
Example:
(1..10).each_with_object([]) { |i, a| a << i*2 }
#=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
reverse_each { |item| block }Builds a temporary array and traverses that array in reverse order, executing the block for each item. If no block is given, an enumerator is returned.
Example:
(1..3).reverse_each { |v| p v }
# produces:
# 3
# 2
# 1
cycle(n=nil) { |obj| block }Calls the block for each element repeatedly n times, or forever if n is nil. If n is non-positive or the collection is empty, does nothing. Returns nil if the loop finishes. If no block is given, an enumerator is returned.
Examples:
a = ["a", "b", "c"]
# a.cycle { |x| puts x } # print, a, b, c, a, b, c,.. forever.
a.cycle(2) { |x| puts x } # print, a, b, c, a, b, c.
find_index(value) / find_index { |obj| block }Compares each entry with value or passes to block. Returns the index for the first non-false evaluation. If no object matches, returns nil. If no argument or block is given, an enumerator is returned.
Examples:
(1..100).find_index { |i| i % 5 == 0 and i % 7 == 0 } #=> 34
(1..100).find_index(50) #=> 49
zip(arg, ...) { |arr| block }Takes one element from the enumerable and merges corresponding elements from each arg. Generates a sequence of n-element arrays. The length will be enum#size. If any argument is shorter, nil values are supplied. If a block is given, it's invoked for each output array; otherwise, an array of arrays is returned.
Examples:
a = [ 4, 5, 6 ]
b = [ 7, 8, 9 ]
a.zip(b) #=> [[4, 7], [5, 8], [6, 9]]
[1, 2].zip(a, b) #=> [[1, 4, 7], [2, 5, 8]]
c = []
a.zip(b) { |x, y| c << x + y } #=> nil
c #=> [11, 13, 15]
to_h { |element| block }Returns a hash by interpreting the enumerable as a list of [key, value] pairs. If a block is given, it's used to transform elements before they are converted into pairs.
Example:
%i[hello world].each_with_index.to_h
# => {:hello => 0, :world => 1}
# With a block (example assumes a suitable block)
# (0..3).to_h {|x| [x, x*x] } # => {0=>0, 1=>1, 2=>4, 3=>9} (Conceptual example)
(The to_h method in the source is a bit complex with its block handling; the example is simplified.)
uniq { |item| block }Returns a new array by removing duplicate values. If a block is given, it will use the return value of the block for uniqueness comparison.
Examples:
[1, 2, 2, 3, 1].uniq #=> [1, 2, 3]
["a", "B", "c", "b"].uniq { |s| s.downcase } #=> ["a", "B", "c"]
filter_map { |obj| block }Returns a new array containing the truthy results of running the block for every element. If no block is given, an enumerator is returned.
Example:
[-2, -1, 0, 1, 2].filter_map { |x| x*2 if x > 0 } #=> [2, 4]
grep_v(pattern) { |obj| block }Returns an array of elements that do NOT match the pattern. If a block is given, the elements of the result are passed to the block and the block's results are returned.
Example:
a = ["apple", "banana", "orange", "grape"]
a.grep_v(/an/) #=> ["apple", "orange", "grape"]
a.grep_v(/an/) { |s| s.upcase } #=> ["APPLE", "ORANGE", "GRAPE"]
tallyTallies the collection. Returns a hash where keys are elements and values are their counts.
Example:
["a", "b", "c", "b"].tally #=> {"a"=>1, "b"=>2, "c"=>1}
sum(initial=0) { |obj| block }Returns the sum of elements. If a block is given, each element is processed by the block before addition. initial is the starting value for the sum.
Examples:
[1, 2, 3].sum #=> 6
[1, 2, 3].sum(10) #=> 16
[1, 2, 3].sum { |x| x * 2 } #=> 12
({a:1, b:2, c:3}).sum {|k,v| v} #=> 6 (Example from Ruby docs, assuming similar behavior)
each_entry(*args) { |obj| block }Calls block once for each element, passing that element as a parameter (converting multiple values from yield to an array). If no block is given, an enumerator is returned.
Example:
class Foo
include Enumerable
def each
yield 1
yield 1, 2
yield
end
end
Foo.new.each_entry{ |o| p o }
# produces:
# 1
# [1, 2]
# nil
Note on Array#sort_by and Array#sort_by!
The gem also provides optimized sort_by and sort_by! methods directly on the Array class. sort_by! sorts the array in place.
arr = ["apple", "pear", "fig"]
arr.sort_by! { |word| word.length }
p arr #=> ["fig", "pear", "apple"]