D7net
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
proc
/
self
/
root
/
opt
/
alt
/
ruby34
/
share
/
ri
/
system
/
Enumerable
/
Filename :
reduce-i.ri
back
Copy
U:RDoc::AnyMethod[iI"reduce:ETI"Enumerable#reduce;TF:publico:RDoc::Markup::Document:@parts[Ao:RDoc::Markup::Paragraph; [ I"FReturns the result of applying a reducer to an initial value and ;TI"Sthe first element of the Enumerable. It then takes the result and applies the ;TI"Mfunction to it and the second element of the collection, and so on. The ;TI"Kreturn value is the result returned by the final call to the function.;To:RDoc::Markup::BlankLine o; ; [I"You can think of;T@o:RDoc::Markup::Verbatim; [I"2[ a, b, c, d ].inject(i) { |r, v| fn(r, v) } ;T:@format0o; ; [I" as being;T@o;; [I"#fn(fn(fn(fn(i, a), b), c), d) ;T; 0o; ; [I";In a way the +inject+ function _injects_ the function ;TI",between the elements of the enumerable.;T@o; ; [I"B+inject+ is aliased as +reduce+. You use it when you want to ;TI"-_reduce_ a collection to a single value.;T@o; ; [I"!<b>The Calling Sequences</b>;T@o; ; [I"'Let's start with the most verbose:;T@o;; [I"8enum.inject(initial_value) do |result, next_value| ;TI"5 # do something with +result+ and +next_value+ ;TI"5 # the value returned by the block becomes the ;TI"/ # value passed in to the next iteration ;TI" # as +result+ ;TI" end ;T; 0o; ; [I"For example:;T@o;; [ I"=product = [ 2, 3, 4 ].inject(1) do |result, next_value| ;TI" result * next_value ;TI" end ;TI"product #=> 24 ;T; 0o; ; [I"PWhen this runs, the block is first called with +1+ (the initial value) and ;TI"Q+2+ (the first element of the array). The block returns <tt>1*2</tt>, so on ;TI"Othe next iteration the block is called with +2+ (the previous result) and ;TI"O+3+. The block returns +6+, and is called one last time with +6+ and +4+. ;TI"PThe result of the block, +24+ becomes the value returned by +inject+. This ;TI"@code returns the product of the elements in the enumerable.;T@o; ; [I"1<b>First Shortcut: Default Initial value</b>;T@o; ; [I"PIn the case of the previous example, the initial value, +1+, wasn't really ;TI"Vnecessary: the calculation of the product of a list of numbers is self-contained.;T@o; ; [I"RIn these circumstances, you can omit the +initial_value+ parameter. +inject+ ;TI"Qwill then initially call the block with the first element of the collection ;TI"Jas the +result+ parameter and the second element as the +next_value+.;T@o;; [I"0[ 2, 3, 4 ].inject do |result, next_value| ;TI" result * next_value ;TI" end ;T; 0o; ; [I"XThis shortcut is convenient, but can only be used when the block produces a result ;TI"9which can be passed back to it as a first parameter.;T@o; ; [I"]Here's an example where that's not the case: it returns a hash where the keys are words ;TI"Qand the values are the number of occurrences of that word in the enumerable.;T@o;; [I"$freqs = File.read("README.md") ;TI" .scan(/\w{2,}/) ;TI". .reduce(Hash.new(0)) do |counts, word| ;TI" counts[word] += 1 ;TI" counts ;TI" end ;TI"freqs #=> {"Actions"=>4, ;TI" "Status"=>5, ;TI" "MinGW"=>3, ;TI" "https"=>27, ;TI" "github"=>10, ;TI" "com"=>15, ... ;T; 0o; ; [I"VNote that the last line of the block is just the word +counts+. This ensures the ;TI"Ereturn value of the block is the result that's being calculated.;T@o; ; [I"/<b>Second Shortcut: a Reducer function</b>;T@o; ; [I"]A <i>reducer function</i> is a function that takes a partial result and the next value, ;TI"Yreturning the next partial result. The block that is given to +inject+ is a reducer.;T@o; ; [I"SYou can also write a reducer as a function and pass the name of that function ;TI"G(as a symbol) to +inject+. However, for this to work, the function;T@o:RDoc::Markup::List: @type:NUMBER:@items[o:RDoc::Markup::ListItem:@label0; [o; ; [I"4Must be defined on the type of the result value;To;;0; [o; ; [I"JMust accept a single parameter, the next value in the collection, and;To;;0; [o; ; [I"JMust return an updated result which will also implement the function.;T@o; ; [I"ZHere's an example that adds elements to a string. The two calls invoke the functions ;TI"PString#concat and String#+ on the result so far, passing it the next value.;T@o;; [ I"3s = [ "cat", " ", "dog" ].inject("", :concat) ;TI"s #=> "cat dog" ;TI"<s = [ "cat", " ", "dog" ].inject("The result is:", :+) ;TI"$s #=> "The result is: cat dog" ;T; 0o; ; [I"DHere's a more complex example when the result object maintains ;TI":state of a different type to the enumerable elements.;T@o;; [I"class Turtle ;TI" ;TI" def initialize ;TI" @x = @y = 0 ;TI" end ;TI" ;TI" def move(dir) ;TI" case dir ;TI" when "n" then @y += 1 ;TI" when "s" then @y -= 1 ;TI" when "e" then @x += 1 ;TI" when "w" then @x -= 1 ;TI" end ;TI" self ;TI" end ;TI" end ;TI" ;TI":position = "nnneesw".chars.reduce(Turtle.new, :move) ;TI"<position #=>> #<Turtle:0x00000001052f4698 @y=2, @x=1> ;T; 0o; ; [I"9<b>Third Shortcut: Reducer With no Initial Value</b>;T@o; ; [I"QIf your reducer returns a value that it can accept as a parameter, then you ;TI"Qdon't have to pass in an initial value. Here <tt>:*</tt> is the name of the ;TI"_times_ function:;T@o;; [I"&product = [ 2, 3, 4 ].inject(:*) ;TI"product # => 24 ;T; 0o; ; [I" String concatenation again:;T@o;; [I"*s = [ "cat", " ", "dog" ].inject(:+) ;TI"s #=> "cat dog" ;T; 0o; ; [I"NAnd an example that converts a hash to an array of two-element subarrays.;T@o;; [I"1nested = {foo: 0, bar: 1}.inject([], :push) ;TI"'nested # => [[:foo, 0], [:bar, 1]];T; 0: @fileI"enum.c;T:0@omit_headings_from_table_of_contents_below000[ I"(p1 = v1, p2 = v2);T@�FI"Enumerable;TcRDoc::NormalModule0[@�FI"inject;T