This is what I have working in a playground, any reason why this is no good?

class Book {
    var author = String()

    init(author:String){
        self.author = author
    }
}

var allBooks: [Book] = []

allBooks.append(Book(author: "John Smith"))
allBooks.append(Book(author: "Arthur Price"))
allBooks.append(Book(author: "David Jones"))
allBooks.append(Book(author: "Somebody Else"))

let authors = ["Arthur Price", "David Jones"]

let filteredBooks = allBooks.filter({authors.contains($0.author)})

filteredBooks       // [{author "Arthur Price"}, {author "David Jones"}]
Answer from Jon-Paul on Stack Overflow
🌐
Reddit
reddit.com › r/swift › filtering array of objects by strings in another array.
r/swift on Reddit: Filtering array of objects by strings in another array.
October 30, 2015 -

I have an array of Match objects [Match] with a string property of matchID. I also have an array of strings.

I would like to remove the Match object where matchID equals any string in the array.

I currently have:

                var matches = [Match]
                var matchIDsToDelete = [String]

                for match in matches {
                    for id in matchIDsToDelete {
                        if match.matchID == id {
                            // remove that item from array
                        }
                    }
                }

My concern is removing the object from the array as I'm enumerating. I believe there will be consequences. Any suggestions? I would also love a functional solution as I'm currently reading more about functional programming.

Thanks!

Top answer
1 of 7
51

contains() checks if a sequence contains a given element, e.g. if a String contains a given Character.

If your intention is to find all books where the name contains the substring "rt", then you can use rangeOfString():

var arr = englishBooks.filter {
    $0.nameOfBook.rangeOfString("rt") != nil
}

or for case-insensitive comparison:

var arr = englishBooks.filter {
    $0.nameOfBook.rangeOfString("rt", options: .CaseInsensitiveSearch) != nil
}

As of Swift 2, you can use

nameOfBook.containsString("rt") // or
nameOfBook.localizedCaseInsensitiveContainsString("rt")

and in Swift 3 this is

nameOfBook.contains("rt") // or
nameOfBook.localizedStandardContains("rt") // or
nameOfBook.range(of: "rt", options: .caseInsensitive) != nil
2 of 7
17

Sorry this is an old thread. Change you code slightly to properly init your variable 'nameOfBook'.

class book{
   var nameOfBook: String!
   init(name: String) {
      nameOfBook = name
   }
}

Then we can create an array of books.

var englishBooks = [book(name: "Big Nose"), book(name: "English Future 
Prime Minister"), book(name: "Phenomenon")]

The array's 'filter' function takes one argument and some logics, 'contains' function can take a simplest form of a string you are searching for.

let list1 = englishBooks.filter { (name) -> Bool in
   name.contains("English")
}

You can then print out list1 like so:

let list2 = arr1.map({ (book) -> String in
   return book.nameOfBook
})
print(list2)

// print ["English Future Prime Minister"]

Above two snippets can be written short hand like so:

let list3 = englishBooks.filter{ ($0.nameOfBook.contains("English")) }
print(list3.map({"\($0.nameOfBook!)"}))
🌐
Programiz
programiz.com › swift-programming › library › array › filter
Swift Array filter() (With Examples)
Swift String removeAll() The filter() method returns all the elements from the array that satisfy the provided condition. var numbers = [2, 3, 6, 9] // return all the elements greater than 5 var result = numbers.filter({ $0 > 5}) print(result) // Output: [6, 9] The syntax of the filter() method is: array.filter(condition) Here, array is an object of the Array class.
🌐
Sarunw
sarunw.com › posts › swift-array-filter
How to Filter an Array in Swift | Sarunw
July 10, 2023 - let names = ["Alice", "Bob", "John"] let shortNames = names.filter { name in if name.count < 4 { // 1 ... 1 We return true for an element we want to keep. In this case, we want to keep a name shorter than four characters, name.count < 4. 2 For other names, we return false to discard them. The resulting array contains only names shorter than four characters which is only **"Bob"**in this case. You can easily support sarunw.com by checking out this sponsor.
🌐
Donny Wals
donnywals.com › how-to-filter-an-array-in-swift
How to filter an Array in Swift? – Donny Wals
April 23, 2024 - When you have an Array of elements, and you want to drop all elements that don't match specific criteria from the Array, you're looking for Array's filter(isIncluded:) method.
Top answer
1 of 2
9

This is unnecessarily complex. There's no need for NSPredicate here.

var studios = [Studio]()
var filteredStudios = [Studio]()
var studiosToDisplay = [Studio]()

func updateSearchResultsForSearchController(searchController: UISearchController) {
    let searchText = searchController.searchBar.text

    print("SEARCH TEXT: \(searchText)")

    if let searchText = searchText, !searchText.isEmpty {
        studiosToDisplay = studios.filter{ $0.studioName.contains(searchText) }
    }
    else {
        studiosToDisplay = studios
        NSNotificationCenter.defaultCenter().postNotificationName("showResultsBeforeSearchingNotification", object: nil) //Calls SearchVC
    }

    self.resultTableView.reloadData()
}
2 of 2
1

Thanks to @Alexander .. Here's the code I ended up using:

func updateSearchResultsForSearchController(searchController: UISearchController) {

    let searchText = searchController.searchBar.text

    if let searchText = searchText {
        if !searchText.isEmpty {
            self.studiosToDisplay = self.studios.filter { $0.studioName!.containsString(searchText) }
            for studio in self.studiosToDisplay {
                print("\(studio.studioName!)")
            }
        }
        else {
            self.studiosToDisplay = self.studios
            NSNotificationCenter.defaultCenter().postNotificationName("showResultsBeforeSearchingNotification", object: nil) // Calls SearchVC
        }
    }

    self.resultTableView.reloadData()

}

I figured out, that my former code, with the NSPredicate actually was functional - I was just presenting the wrong array in my tableview.. Oops.. But now it works, and I stick to the more simple code. Don't know why I didn't think of using the $0-function :) .. Anyway, thanks!

🌐
Swift Forums
forums.swift.org › using swift
Filter array with another array - Using Swift - Swift Forums
June 29, 2022 - I would like to create a new array of strings that dont contain strings from another array. I have it working in the long form. But would like to learn a more Swift way of doing it The return filteredList would be ["music", "unicorns rainbow walkers"] let removelist : [String] = ["nerf", "magic beans"] let originalList : [String] = ["nerf", "music", "unicorns rainbow walkers", "magic beans"] // tried this but not exactly working //let filtered = originalList.filter { $0.contains(where: { rem...
Find elsewhere
Top answer
1 of 5
161

// this is not working - NSArray is not a subtype of Images- so what if there is only 1 possible result?

You have no way to prove at compile-time that there is only one possible result on an array. What you're actually asking for is the first matching result. The easiest (though not the fastest) is to just take the first element of the result of filter:

let imageObject = questionImageObjects.filter{ $0.imageUUID == imageUUID }.first

imageObject will now be an optional of course, since it's possible that nothing matches.

If searching the whole array is time consuming, of course you can easily create a firstMatching function that will return the (optional) first element matching the closure, but for short arrays this is fine and simple.


As charles notes, in Swift 3 this is built in:

questionImageObjects.first(where: { $0.imageUUID == imageUUID })
2 of 5
32

Edit 2016-05-05: Swift 3 will include first(where:).

In Swift 2, you can use indexOf to find the index of the first array element that matches a predicate.

let index = questionImageObjects.indexOf({$0.imageUUID == imageUUID})

This is bit faster compared to filter since it will stop after the first match. (Alternatively, you could use a lazy sequence.)

However, it's a bit annoying that you can only get the index and not the object itself. I use the following extension for convenience:

extension CollectionType {
    func find(@noescape predicate: (Self.Generator.Element) throws -> Bool) rethrows -> Self.Generator.Element? {
        return try indexOf(predicate).map({self[$0]})
    }
}

Then the following works:

questionImageObjects.find({$0.imageUUID == imageUUID})
🌐
Medium
medium.com › swlh › filtering-in-swift-8524bbd55119
Filtering in Swift. Filtering is an extremely important… | by Steven Curtis | The Startup | Medium
February 20, 2022 - Filter: Acts on a collection type and returns an Array where the elements that are returned match the condition given in the Array · Set: An unordered collection of values (where all the values are of the same type) A filter acts on any collection ...
Top answer
1 of 3
2
import UIKit

First of all you don't need to inherit from NSObject. Also, if you don't need reference semantics, use structs instead.

struct TicketsCellModel {
  var title: String?
  var text: String?
  var price: String?
  var tintColor: UIColor?
  var quantity: Int?
}

It's not really necessary to use a closure to create an [TicketsCellModel]. Just assign the elements directly. Since we're using structs we don't need to create a separate init.

var ticketCellModels = [
  TicketsCellModel(
    title: "Standard Entry",
    text: "This is aa standard entry ticket, it's not sutiable for special events please see the plus ticket for that.",
    price: "£8.35",
    tintColor: UIColor.white,
    quantity: 0
  ),
  TicketsCellModel(
    title: "Standard with re-entry",
    text: "This is a standard entry ticket but you can come and go as you please during the night.",
    price: "£8.99",
    tintColor: UIColor.white,
    quantity: 2
  ),
  TicketsCellModel(
    title: "Plus Entry",
    text: "This is the plus entry ticket for special events.",
    price: "£9.99",
    tintColor: UIColor.white,
    quantity: 0
  ),
  TicketsCellModel(
    title: "VIP Entry",
    text: "Here is some more text that is to act as a description for this thing you will purchase.",
    price: "£12.99",
    tintColor: UIColor.white,
    quantity: 4
  )
]

Now, if you need to access an optional, you will have to unwrap it first. The safest way to do this is using the if let construct or using the nil-coalescing operator.

let filteredTicketCellModels = ticketCellModels.filter { $0.quantity ?? 0 > 0 }

print(filteredTicketCellModels)

In the example above there are no unknown variables during initialization, so maybe non-optional properties might be better suited. Then you don't have to unwrap anything.

Leo Dabus adds that it is recommended that all properties be constants. The way to do this is to replace all vars with lets. If you need to change a property you can create a new object copying the properties from the old one and adding the new values to the properties that have changed.

2 of 3
0

If you want a quick and safe fix, you can use the nil coalescing operator ?? to have item.quantity = 0 when it's equal to nil.

It'd look like this:

let filteredTicketCellModels = ticketCellModels.filter( { return ($0.quantity ?? 0 > 0)! } )
    for item in filteredTicketCellModels {
        print("qty: \(item.quantity)")
    }

The reason why your filtering by titles doesn't crash is because none of your optional variables contain nil. If item.title were == to nil however, that bang (!) at the end of it causes a crash upon variable access.

If titles (or any other variables within your class) are never nil, you should declare them as just var title: String , without the ? at the end (which would mean you have to actually have an initializer for your object too! (which is better practice anyways :) ))

🌐
Hacking with Swift
hackingwithswift.com › books › ios-swiftui › dynamically-filtering-a-swiftui-list
Dynamically filtering a SwiftUI List - a free Hacking with iOS: SwiftUI Edition tutorial
January 3, 2022 - In our app, we have three instances of ProspectsView that vary only according to the FilterType property that gets passed in from our tab view. We’re already using that to set the title of each view, but we can also use it to set the contents ...
🌐
Apple Developer
developer.apple.com › forums › thread › 693772
filter an object array based on an… | Apple Developer Forums
How can you judge if an Option exist in the selected Array? Compare userCode? Compare optType? Compare optValue? Or some other way? ... extension Selected { func matches(_ option: Option) -> Bool { //↓Modify the following expression to fit for your purpose return optType == option.optType && optValue == option.optValue } } ... Button("Options Not Selected") { let optionsNotSelected = options.filter { option in !selected.contains {$0.matches(option)} } print(optionsNotSelected) //Use `optionsNotSelected`... }
🌐
DhiWise
dhiwise.com › post › efficient-data-refinement-with-swift-array-filter-strategies
Mastering Swift Array Filter: A Comprehensive Guide
September 10, 2024 - Build 10x products in minutes by chatting with AI - beyond just a prototype. ... Understanding Swift ArraysFiltering Arrays in SwiftInitial Value for FilteringFilter Elements based on Boolean ValueUsing Higher Order FunctionsPractical Example of Array FilteringPerformance Considerations in Array FilteringConclusion
🌐
YouTube
youtube.com › hey delphi
Array : Filter an array of objects by property, using an array of values in Swift - YouTube
Array : Filter an array of objects by property, using an array of values in SwiftTo Access My Live Chat Page, On Google, Search for "hows tech developer conn...
Published   May 5, 2023
Views   2
🌐
Cocoa Casts
cocoacasts.com › swift-fundamentals-how-to-find-an-object-in-an-array
How to Find an Object in an Array
The filter(_:) method accepts a closure as its only argument. The closure accepts an object of type Int and its return value is Bool. The resulting array includes every object of the array for which the closure returns true. Like many other programming languages, Swift includes a wide range ...
🌐
Reddit
reddit.com › r/swift › predicate to filter by a property inside of an array. swiftdata & swiftui
r/swift on Reddit: Predicate to filter by a property inside of an array. SwiftData & SwiftUI
April 30, 2023 -

Hi.

I want to filter by a property inside of an array but I can't find a why to make it work. I already tried different options but none of them work. Xcode throws this error:

Cannot convert value of type 'PredicateExpressions.SequenceContainsWhere<PredicateExpressions.KeyPath<PredicateExpressions.Variable<Excercise>, [Muscle]>, PredicateExpressions.Equal<PredicateExpressions.KeyPath<PredicateExpressions.Variable<Muscle>, String>, PredicateExpressions.KeyPath<PredicateExpressions.Value<Muscle>, String>>>' to closure result type 'any StandardPredicateExpression<Bool>'

This is the code:

if let muscle {
    let predicate = #Predicate<Exercise> { exercise in
        exercise.muscles.contains { _muscle in
            _muscle.id == muscle.id
        }
    }
    _exercises = Query(filter: predicate)
}

Models:

Exercise

@Model
final class Exercise: Identifiable {
    @Attribute(.unique) 
    let id = UUID().uuidString
    var name: String
    @Relationship(deleteRule: .nullify)
    let muscles: [Muscle]
    
    init(name: String, muscles: [Muscle] = []) {
        self.name = name
        self.muscles = muscles
    }
}

Muscle

@Model
final class Muscle: Identifiable, Equatable {
    @Attribute(.unique)
    let id = UUID().uuidString
    let name: String
    let icon: String
    let color: String
    
    init(name: String, icon: String, color: String) {
        self.name = name
        self.icon = icon
        self.color = color
    }
    
    static func == (lhs: Muscle, rhs: Muscle) -> Bool {
        lhs.id == rhs.id
    }
}

Thanks!