Swift: Can Not Use Array Filter in If Let Statement Condition

Swift: Can not use array filter in if let statement condition

You can make this work by putting parentheses around the closure that you're passing to filter:

if let selected = users.filter({$0.characters.count == 2}).first {
print(selected)
}

That is the right way to do it. The trailing closure syntax doesn't work very well sometimes on lines with extra elements. You could also put parentheses around the whole statement:

if let selected = (users.filter {$0.characters.count == 2}.first) {
print(selected)
}

Swift is just having trouble parsing your statement. The parentheses give it help in how to parse the line. You should prefer the first way since the closure is indeed a parameter of filter, so enclosing it in parentheses makes it clear to Swift that you are passing it to filter.

How does filter know what the condition is if it is supposed to just return a boolean value?

filter iterates over all elements of the Array it is called on, executes the same closure for each element and returns a new array, which only contains the elements, for which the closure returned true.

How does this code know to get only the booking values if this: $0.startdate!.toString(dateFormat: "yyyy-MM-dd").contains(selectedDate) is just returning a boolean value? It must also return an array right? (or a copy / reference of one)

As explained above, the condition in that closure is executed for each element of bookings and filter returns a new Array, which contains only the elements for which the closure returned true.

Your second expression with the nested ternary expression is actually equivalent to your first expression without the nested ternary expression. If you look at it more closely,
$0.startdate!.toString(dateFormat: "yyyy-MM-dd").contains(selectedDate) ? true : !$0.startdate!.toString(dateFormat: "yyyy-MM-dd").contains(selectedDate), the expression after the : is simply the negated version of the condition of your ternary expression. So basically, this means a ? true : !a, which is equivalent to a itself.

If you want to achieve

So based on that, I wanted to add more functionality so that if the user selected a date where there were no matches, all of the bookings are displayed.

, I would suggest saving the result of your original filter into a local variable, then checking whether this array is empty, if not, call ForEach on the filtered array, otherwise call it on bookings.

let bookingsForSelectedDate = self.bookings.filter { self.selectedDate.isEmpty ? true : $0.startdate!.toString(dateFormat: "yyyy-MM-dd").contains(selectedDate) }
let matchingOrAllBookings = !bookingsForSelectedDate.isEmpty ? bookingsForSelectedDate : self.bookings
ForEach(matchingOrAllBookings, id: \.self) { booking in
NavigationLink(destination: BookingDetail(theBooking: booking)) {
HStack {
...
}}

Swift filter array by condition

It should be simple until unless you don't have some other requirement.

cats.filter { $0.id == 7 }

And to skip optional values you can use compactMap

e.g

let array: [Cat] = [
Cat(id: 7, name: "CatA"),
Cat(id: nil, name: "CatB"),
Cat(id: 1, name: "CatC"),
Cat(id: 7, name: "CatD"),
Cat(id: 7, name: "CatE"),
Cat(id: 2, name: "CatF"),
Cat(id: nil, name: "CatG"),
]

print(array.compactMap { value -> Cat? in
guard let id = value.id, id > 2 else { return nil }
return value
})

Why is result of filter with count not usable directly as conditional in Swift 3

Swift has trouble parsing anonymous closure in the context of an if logical expression. You can work around this issue by parenthesizing the count expression:

if (myStructArray.filter{$0.isLocked == true}.count) < 4 {
// ^ ^
print("Fewer than 4 locked")
}

or

if (myStructArray.filter{$0.isLocked == true}.count < 4) {
// ^ ^
print("Fewer than 4 locked")
}

or

if myStructArray.filter({$0.isLocked == true}).count < 4 {
// ^ ^
print("Fewer than 4 locked")
}

Swift filter with condition

Append

&& IoC.filterDataService.autoTransmision ? $0.car.gearingType == .automatic : true

to your initial conditions

Get output out of filter when there are no results

You need to check if your filtered array in if is empty:

let filteredArray = array.filter({...})
if !filteredArray.isEmpty {
ForEach(filteredArray) { item in
// do things if found
}
} else {
Text("No results at all")
}

Filter by multiple array conditions

Forget about the filter for a moment. Think how you would check if a car's color is a value in an array.

let colors = [ "Green", "Blue" ]
// or let colors: Set = [ "Green", "Blue" ]
if colors.contains(someCar.color) {
}

Simple enough. Now use that same simple expression in the filter.

let filterdObject = cars.filter { $0.model == currModel || colors.contains($0.color) }


Related Topics



Leave a reply



Submit