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.
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.
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.
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.
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.
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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With