Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

break out of filter() function

I'd like to optimize my functions which rely on filter(). In some cases I want to break out of them when they reach a certain elements. (For example, I may have an array of distinct elements. Or, I just want to implement a kind of findFirst functionality.) In such instances it seems inefficient for the function to continue until the end of the array.

This is something very easy with loops, but I would like to apply the optimisations to functional programming principals. (The compiler wouldn't be able to perform such a optimization by itself, since it doesn't know my array and my intention.)

Can this be done?

like image 877
Daniel Avatar asked Jun 28 '15 15:06

Daniel


People also ask

How do you break an array filter?

You can just use for loop and when function returns true you can just break loop and return results from that index. You can also use findIndex() and if match is found you can slice array from that index otherwise return empty array.

What is filter () in JavaScript?

The filter() method creates a new array filled with elements that pass a test provided by a function. The filter() method does not execute the function for empty elements. The filter() method does not change the original array.

What does the filter function return?

An array can be thought of as a row of values, a column of values, or a combination of rows and columns of values. In the example above, the source array for our FILTER formula is range A5:D20. The FILTER function will return an array, which will spill if it's the final result of a formula.

Does filter return an object?

The filter() function will return a new array containing all the array elements that pass the given condition. If no elements pass the condition it returns an empty array. The filter() function loops or iterate over each array element and pass each element to the callback function.


3 Answers

There is first(where:) that breaks out when it finds the first passing case:

let data = ["Alpha","Beta","Gamma","Delta"]

let b2 = data.first(where:{$0=="Beta"})
like image 123
DavidA Avatar answered Oct 18 '22 04:10

DavidA


filter isn’t written to break out like that. I don’t believe there’s an out-of-the-box way to do the kind of thing you’re looking for.

Generally it’s better to avoid making functions more flexible to cover narrow cases. Adding early bail might be useful sometimes but would come at the cost of complicating filter, and the code would probably be hard to read (bear in mind one of the main goals of using functions like filter, map etc is to make the code easier to read and to be certain the code is correct). Some functions do support early exit though, when it’s fundamental to their purpose - for example, contains or indexOf.

But it’s not too hard to create your own higher-order functions to do what you want, the name of which makes their intent pretty clear. For example, to take all the elements in a sequence up to the first one that doesn’t match a pattern, you could write takeWhile like this:

extension SequenceType {
    func takeWhile(condition: Generator.Element -> Bool) -> [Generator.Element] {
        var result: [Generator.Element] = []
        for x in self {
            guard condition(x) else { break }
            result.append(x)
        }
        return result
    }
}



let nums = [1,3,1,2]
let isOdd = { $0%2 == 1 }
let initialOdd = nums.takeWhile(isOdd)
print(initialOdd)
like image 8
Airspeed Velocity Avatar answered Oct 18 '22 05:10

Airspeed Velocity


The point of using filter is to factor out the predicate and scan the whole collection. You can't find out which data to filter till you went thru the whole data set. In its basic form filter is just a check on the a condition (predicate) to construct a new collection:

let bools = [true, false, false, true]

print(bools.filter {$0})

What you are asking is gaining control of the iterator loop in filter while filter is implemented to simplify it by hiding it. I suggest you use the control flow statements built in the language (if, for, etc, continue, break) to give you what you need. No point forcing weird syntax statements that make your code looks more convoluted and ungrokable.

like image 3
John Difool Avatar answered Oct 18 '22 03:10

John Difool