Arguments | = | Argumentable | DEPRECATED: Module alias for old name. |
Accumulate a set of a set. For example, in an ORM design where `Group has_many User` we might have something equivalent to the following.
Group = Struct.new(:users) User = Struct.new(:name, :friends) user1 = User.new('John', []) user2 = User.new('Jane', ['Jill']) user3 = User.new('Joe' , ['Jack', 'Jim']) group1 = Group.new([user1, user2]) group2 = Group.new([user2, user3]) groups = [group1, group2]
Now we can accumulate the users of all groups.
groups.accumulate.users #=> [user1, user2, user3]
You may pass an argument to perform chains, e.g. the following returns the names of users from all groups.
groups.accumulate(2).users.name #=> ['John','Jane','Joe']
Or we can gather all the friends of all users in groups.
groups.accumulate(2).users.friends #=> ['Jill','Jack','Jim']
This is more convenient then the equivalent.
groups.accumulate.users.accumulate.friends #=> ['Jill','Jack','Jim']
CREDIT: George Moshchovitis, Daniel Emirikol, Robert Dober
Same as accumulate, but does not apply uniq to final result.
groups.accumulate_all(2).users.friends #=> ['Jill', 'Jill','Jack','Jim']
Returns an elemental object. This allows you to map a method on to every element.
r = [1,2,3].apply.+ r #=> 6
Clusters together adjacent elements into a list of sub-arrays.
[2,2,2,3,3,4,2,2,1].cluster{ |x| x } => [[2, 2, 2], [3, 3], [4], [2, 2], [1]] ["dog", "duck", "cat", "dude"].cluster{ |x| x[0] } => [["dog", "duck"], ["cat"], ["dude"]]
@author Oleg K
Without a block: wrap the Enumerable object in such a way that map, select and similar operations are performed "horizontally" across a series of blocks, instead of building an array of results at each step. This reduces memory usage, allows partial results to be provided early, and permits working with infinite series.
a = (1..1_000_000_000).defer.select{ |i| i % 2 == 0 }. map{ |i| i + 100 }. take(10).to_a
With a block: the block acts as an arbitrary filter on the data. Unlike map, it can choose to drop elements from the result, and/or add additional ones. The first object passed to the block is the receiver of the output.
(1..1_000_000_000). defer { |out,i| out << i if i % 2 == 0 }. # like select defer { |out,i| out << i + 100 }. # like map take(10).to_a
Use a method like to_a or to_h at the end of the chain when you want an Array or Hash built with the results, or each{…} if you just want to output each result and discard it.
Iterate through slices. If slice steps is not given, the arity of the block is used.
x = [] [1,2,3,4].each_by{ |a,b| x << [a,b] } x #=> [ [1,2], [3,4] ] x = [] [1,2,3,4,5,6].each_by(3){ |a| x << a } x #=> [ [1,2,3], [4,5,6] ]
This is just like each_slice, except that it will check the arity of the block. If each_slice ever suppots this this method can be deprecated.
CREDIT: Trans
Returns an elemental object. This allows you to map a method on to every element.
r = [1,2,3].every + 3 r #=> [4,5,6]
Returns an elementwise Functor designed to make R-like elementwise operations possible. This is very much like the every method, but it treats array argument specially.
([1,2].ewise + 3) #=> [4,5]
Vector to vector
([1,2].ewise + [4,5]) #=> [5,7]
Special thanks to Martin DeMello for helping to develop this.
Expand all elements of an Enumerable object.
[0, 2..3, 5..7].expand #=> [0,[2, 3],[5,6,7]]
CREDIT: Trans
The block acts as an arbitrary filter on the data. Unlike map, it can choose to drop elements from the result and/or add additional elements. The first object passed to the block is the receiver of the output.
x = (1..10000) x = x.filter{ |out,i| out << i if i % 2 == 0 } # like select x = x.filter{ |out,i| out << i + 100 } # like map x = x.take(3) x #=> [102, 104, 106]
This is very similar to each_with_object, but filter handles argument better by reversing their order and using the splat operator. (This was also once known as injecting.)
CREDIT: David Black, Louis J Scoras
Yield each element to the block and return the result of the block when that result evaluates as true, terminating early like detect and find.
obj1 = Object.new obj2 = Object.new def obj1.foo?; false; end def obj2.foo?; true ; end def obj1.foo ; "foo1"; end def obj2.foo ; "foo2"; end [obj1, obj2].find_yield{ |obj| obj.foo if obj.foo? } #=> "foo2"
Another example.
[1,2,3,4,5].find_yield{ |i| j = i+1; j if j % 4 == 0 } #=> 4
If the block is never true, return the object given in the first parameter, or nil if none specified.
[1,2,3].find_yield{ |_| false } #=> nil [false].find_yield(1){ |_| false } #=> 1
Generates a hash mapping each unique symbol in the array to the absolute frequency it appears.
[:a,:a,:b,:c,:c,:c].frequency #=> {:a=>2,:b=>1,:c=>3}
CREDIT: Brian Schröder
Like `map`/`collect`, but generates a Hash. The block is expected to return two values: the key and the value for the new hash.
numbers = (1..3) squares = numbers.graph{ |n| [n, n*n] } # { 1=>1, 2=>4, 3=>9 } sq_roots = numbers.graph{ |n| [n*n, n] } # { 1=>1, 4=>2, 9=>3 }
CREDIT: Andrew Dudzik (adudzik), Trans
The hashify methods is a higher-order message used to convert an enumerable object into a hash. Converting an enumerable object into a hash is not a one-to-one conversion, for this reason hashify is used to provide variant approches for the conversion most suited to the use case at hand. Here are some (but not a complete set of) examples.
If the enumerable is a collection of perfect pairs, like that which Hash#to_a generates, then assoc can be used.
a = [ [:a,1], [:b,2] ] a.hashify.assoc #=> { :a=>1, :b=>2 }
If it it contains only arrays, but are not perfect pairs, then concat can be used.
a = [ [:a,1,2], [:b,2], [:c], [:d] ] a.hashify.concat #=> { :a=>[1,2], :b=>[2], :c=>[], :d=>[] }
If the array contains objects other then arrays then the splat method might do the trick.
a = [ [:a,1,2], 2, :b, [:c,3], 9 ] a.hashify.splat #=> { [:a,1,2]=>2, :b=>[:c,3], 9=>nil }
Also, the particular dispatch can be left up the Hashify using the auto method. See Hashify#auto for details on this.
TODO: This method takes arguments only for the sake of the old method which has been deprecated. These will be removed eventually.
CREDIT: Robert Klemme, Sandor Szücs, Trans
Apply each element of an enumerable ot a hash by iterating over each element and yielding the hash and element.
[1,2,3].hinge{|h,e| h[e] = e+1 } #=> {1=>2, 2=>3, 3=>4}
TODO: Enumerable#hinge will get a new name.
The same as include? but tested using #=== instead of #==.
[1, 2, "a"].incase?(2) #=> true [1, 2, "a"].incase?(String) #=> true [1, 2, "a"].incase?(3) #=> false
Why the name `incase`? Because the method uses case-equality. Along with the alliteration for "in case" and the similarity with "include?", it seemed like the perfect fit.
@author Lavir the Whiolet
Convert enumerable into a Hash, iterating over each member where the provided block must return the key to by used to map to the value.
Examples:
[:a,:b,:c].key_by{ |v| v.to_s } #=> {'a'=>:a, 'b'=>:b, 'c'=>:c}
TODO: How should this method behave with a Hash?
Returns: Hash
Like group_by, but maps the second value returned from the block.
a = [1,2,3,4,5] a.map_by{ |e| [e % 2, e + 1] } #=> { 0=>[3,5], 1=>[2,4,6] }
Works well with a hash too.
h = {"A"=>1, "B"=>1, "C"=>1, "D"=>2, "E"=>2} h.map_by{ |k,v| [v, k.downcase] } #=> {1=>["a", "b", "c"], 2=>["d", "e"]}
If a second value is not returned, map_by acts like group_by.
h = {"A"=>1, "B"=>1, "C"=>1, "D"=>2, "E"=>2} h.map_by{ |k,v| v } #=> {1=>[["A",1], ["B",1], ["C",1]], 2=>[["D",2], ["E",2]]}
Send a message to each element and collect the result.
[1,2,3].map_send(:+, 3) #=> [4,5,6]
CREDIT: Sean O‘Halpin
Map each element into another class via class constructor.
@param [new] to_class
Generally a class, but any object that repsonds to #new.
Combines zip and map in a single efficient operation.
h = {} [1,2,3].map_with [:x,:y,:z] do |n,k| h[k] = n end h #=> {:x=>1, :y=>2, :z=>3}
@return [Hash]
@author Michael Kohl
Same as collect but with an iteration counter.
a = [1,2,3].collect_with_index { |e,i| e*i } a #=> [0,2,6]
CREDIT: Gavin Sinclair
Like `map`/`collect`, but generates a Hash. The block is expected to return two values: the key and the value for the new hash.
numbers = (1..3) squares = numbers.mash{ |n| [n, n*n] } # { 1=>1, 2=>4, 3=>9 } sq_roots = numbers.mash{ |n| [n*n, n] } # { 1=>1, 4=>2, 9=>3 }
CREDIT: Andrew Dudzik (adudzik), Trans
Divide an array into groups by modulo of the index.
[2,4,6,8].modulate(2) #=> [[2,6],[4,8]]
CREDIT: Trans
NOTE: Would the better name for this be ‘collate’?
Returns an array of elements for the elements that occur n times. Or according to the results of a given block.
a = [1,1,2,3,3,4,5,5] a.occur(1).sort #=> [2,4] a.occur(2).sort #=> [1,3,5] a.occur(3).sort #=> [] a.occur(1..1).sort #=> [2,4] a.occur(2..3).sort #=> [1,3,5] a.occur { |n| n == 1 }.sort #=> [2,4] a.occur { |n| n > 1 }.sort #=> [1,3,5]
Returns the only element in the enumerable. Raises an IndexError if the enumreable has more then one element.
[5].only # => 5 expect IndexError do [1,2,3].only end expect IndexError do [].only end
CREDIT: Lavir the Whiolet, Gavin Sinclair, Noah Gibbs
Does this Enumerable have the only element?
It differs from Enumerable#one? in that it does not check the items themselves. It checks the quantity only.
CREDIT: Lavir the Whiolet
Similar to group_by but returns an array of the groups. Returned elements are sorted by block.
%w{this is a test}.organize_by {|x| x[0]} #=> [ ['a'], ['is'], ['this', 'test'] ]
CREDIT: Erik Veenstra
Like `each_slice(2)` but ensures the last element has a pair if odd sized.
[:a,1,:b,2,:c,3].pair.to_a #=> [[:a,1],[:b,2],[:c,3]]
Per element meta-functor.
([1,2,3].per(:map) + 3) #=> [4,5,6] ([1,2,3].per(:select) > 1) #=> [2,3]
Using fluid notation.
([1,2,3].per.map + 3) #=> [4,5,6] ([1,2,3].per.select > 1) #=> [2,3]
A versitle compaction method. Like map but used to filter out multiple items in a single step.
Without trash arguments nil is assumed.
[1, nil, 2].purge #=> [1,2]
If trash arguments are given, each argument is compared for a match using #==.
(1..6).purge(3,4) #=> [1,2,5,6]
If a block is given, the yield is used in the matching condition instead of the element itsef.
(1..6).purge(0){ |n| n % 2 } #=> [1,3,5]
NOTE: This could just as well be an override of the core compact method, but to avoid potential issues associated with overriding core methods we use the alternate name purge.
CREDIT: Trans
Returns a recursive functor, that allows enumerable methods to iterate through enumerable sub-elements. By default it only recurses over elements of the same type.
Squeeze out the same elements. This behaves like C++ unique(), removing equivalent elements that are concomitant to each other. To get a similar result with Array#uniq, the array would have to be sorted first.
Calculation order is O(n).
Examples
[1,2,2,3,3,2,1].squeeze #=> [1,2,3,2,1] [1,2,2,3,3,2,1].sort.squeeze #=> [1,2,3] [1,2,2,3,3,2,1].squeeze(*[3]) #=> [1,2,2,3,2,1]
Returns [Array].
CREDIT: T. Yamada
Uses #+ to sum the enumerated elements.
[1,2,3].sum #=> 6 [3,3,3].sum #=> 9
Note that Facets’ sum method is completely generic — it can work on any objects that respond to #+.
[[1],[2],[3]].sum #=> [1,2,3]
For this reason it is usually a good idea to provide a default value. Consider the difference between the two expressions below.
[].sum #=> nil [].sum(0) #=> 0
This default value also acts as an initial value.
[].sum(5) #=> 5 [1,2,3].sum(10) #=> 16
A block can also be passed to coax the elements before summation.
[1.1,2.2,3.3].sum(10.4, &:to_i) #=> 16.4
Notice the initial value is not effected by the block.
@author Dawid Marcin Grzesiak
Like Enumerable#map_send but each iteration is processed via a separate thread.
CREDIT: Sean O‘Halpin
Take an associative array and unassociate it.
[[:a,1], [:b,2]].unassociate.to_a #=> [:a, [1], :b, [2]] [[:a,1], [:b,2]].unassociate(1).to_a #=> [:a, 1, :b, 2]
Like uniq, but determines uniqueness based on a given block.
(-5..5).to_a.uniq_by {|i| i*i } #=> [-5, -4, -3, -2, -1, 0]
Create a hash whose keys are the enumerable‘s elements, with specified values.
If no block is given, the given parameter (default true) is used for all values, e.g.:
[1,2,3].value_by{ true } #=> {1=>true, 2=>true, 3=>true} [1,2,3].value_by{ "a" } #=> {1=>"a", 2=>"a", 3=>"a"}
If a block is given, each key‘s value is the result of running the block for that key, e.g.:
[1,2,3].value_by{ |n| "a"*n } #=> {1=>"a", 2=>"aa", 3=>"aaa"}
@author Ronen Barzel
Recursively iterate over all Enumerable elements, or subset given :type=>[type1, type2, …].
[1, 2, 8..9].visit{ |x| x.succ } # => [2, 3, [9, 10]]