Scott
Scott

Reputation: 21

Swift How to filter an array within an array

I have an array defined as:

var MyArrayOfPaintings = [Painting]()

where Painting is defined as:

struct Painting{
    let Artist: String
    let Name: String
    let ThumbNailURL: String
    var PaintsUsed: [Paint]
}

and Paint is defined as:

struct Paint{
    var PaintType: String
    var PaintColorName: String
}

Normally if I want to filter this array based on the Name property within my search bar I would simply add a line as such:

FilteredArray = MyArrayOfPaintings.filter({$0.Name.lowercased().contains(searchText.lowercased())})

This works fine, but now inside my search bar I would also like to be able to search and then filter on MyArray where PaintColorName is the searched value.

How can I filter MyArrayOfPaintings based an a PaintColourName that is provided how do you essentially filter an array based on a array of structs inside it?

Upvotes: 0

Views: 138

Answers (1)

Leo Dabus
Leo Dabus

Reputation: 236340

Not related to your question but you can use localizedCaseInsensitiveContains instead of lowercasing name and search text. Regarding your question you can filter the paints that contains the color name.

struct Painting {
    let artist: String
    let name: String
    let thumbNailURL: String
    var paints: [Paint]
}

struct Paint {
    var type: String
    var colorName: String
}

var paintings: [Painting] = [.init(artist: "Artist A", name: "Name A", thumbNailURL: "url1", paints: [.init(type: "a", colorName: "white"), .init(type: "b", colorName: "black")]),
                             .init(artist: "Artist B", name: "Name B", thumbNailURL: "url2", paints: [.init(type: "c", colorName: "red"), .init(type: "d", colorName: "green")])]

let searchText = "green"
let filtered = paintings.filter { $0.paints.contains {$0.colorName.localizedCaseInsensitiveContains(searchText) } }

print(filtered) // [Painting(artist: "Artist B", name: "Name B", thumbNailURL: "url2", paints: [Paint(type: "c", colorName: "red"), Paint(type: "d", colorName: "green")])]

If you would like to get only the paint you can use flatMap instead of filter and then filter instead of contains:

let paints = paintings.flatMap { $0.paints.filter {$0.colorName.localizedCaseInsensitiveContains(searchText) } }

paints  // [{type "d", colorName "green"}]

Upvotes: 1

Related Questions