Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stopping a Reduce() operation mid way. Functional way of doing partial running sum

Tags:

I have been doing some functional programming and had a question. Perhaps I might be missing something but is there any way to stop a "reduce()" function midway? Lets say when I reach a certain condition? The idea somehow seems anti functional. I haven't seen any such option in python or F#,

As an example, lets say I have a list such as [1,2,3,4,5]. I want to sum the elements in this list until the sum is not greater than some number (lets say 8), and return/mark/store/identify somehow, the number of elements I have actually added.

If we looked at python for example for I might try something like

reduce(lambda a,b : a if a + b > 8 else a + b, input) 

This gives me the right answer 6, but how do I find that I had added 3 elements to get here. There is no counter as such. I can't do assignments inside lambdas. I think F# has the same situation.

I know I can use a for loop or use a function that can store state etc. But what would be the functional way of doing/thinking about this. Reduce() wants to run until the end, but somewhere along this line of processing, we either want to stop it (because we don't care about processing the rest of the elements) or at least make a note of the place where we stopped caring.

like image 531
Chaitanya Avatar asked Jun 28 '10 05:06

Chaitanya


People also ask

What is the use of reduce () function?

reduce() returns the value that is returned from the callback function on the final iteration of the array. reduce() is a central concept in functional programming, where it's not possible to mutate any value, so in order to accumulate all values in an array, one must return a new accumulator value on every iteration.

What is the purpose of the reduce () function Python?

Python's reduce() is a function that implements a mathematical technique called folding or reduction. reduce() is useful when you need to apply a function to an iterable and reduce it to a single cumulative value.

What is reduce function in python w3schools?

The reduce() function facilitates a functional approach to Python programming. It performs a rolling-computation as specified by the passed function to the neighboring elements, by taking a function and an iterable as arguments, and returns the final computed value.

How do you create a reduce function in Python?

Reduce function is an inbuilt function in python whose major task is to give aggregate value as an output. Syntactically it is written as; reduce(func,iter_obj) here reduce operation will be done on “func” function and “iter_obj” is implying the iterable data values used to return result of output.


2 Answers

Reduce is often used in combination with map. Google for example has developed a map-reduce framework for querying their databases and this map-reduce pattern is now used in several other projects (e.g. CouchDB, Hadoop, etc).

First, you need to map the input variables [2, 1, 3, 4, 5] to something like:

[(1, 2), (1, 1), (1, 3), (1, 4), (1, 5)] 

In that case, x[0] will represent the number of the elements to get the sum x[1]. Of course, the number of elements is 1 at the beginning for each single element.

The next thing then, is to operate on those tuples:

reduce(     lambda a, b: a if a[1] + b[1] > 8 else (a[0] + b[0], a[1] + b[1]),     map(lambda x: (1, x), input)) 

This will return (3, 6), meaning the partial sum is 6 using 3 elements.

I hope you got the idea behind map-reduce-algorithms.

Regards,
Christoph

like image 99
tux21b Avatar answered Sep 21 '22 19:09

tux21b


I agree with JaredPar that writing your own recursive function that behaves similarly to fold, but allows you to stop the computation earlier is the best approach. The way I would write it is a bit more general (so that you can use the function for any situation where you need folding that can stop earlier):

// Generalized 'fold' function that allws you to stop the execution earlier // The function 'f' has a type 'State -> 'T -> Option<'State> // By returning 'None' we can stop the execution (and return the  // current state), by returning Some(newState), we continue folding let rec foldStop f state input =    match input with   | x::xs ->        match f state x with       | None -> state       | Some(newState) -> foldStop f newState xs   | [] -> state  // Example that stops folding after state is larger than 10 foldStop (fun st n -> if st > 10 then None else Some(st + n)) 0 [ 1 .. 10 ] 

This is a very general function and you can use it for all similar scenarios. The nice thing about writing it is that you will never need to write similar explicit recursion again (because you can just use foldStop once you have it).

Note that you can use foldStop to implement fold by always wrapping the result of the accumulation function in 'Some' (so it is more general):

let fold f state input =    foldStop (fun st n -> Some(f st n)) state input 
like image 37
Tomas Petricek Avatar answered Sep 21 '22 19:09

Tomas Petricek