user1162328
user1162328

Reputation:

How to filter objects from an array of Strings in Swift

I have an array of allMenuItems as below, which I am trying to filter from an array of Id's. How is this achievable in Swift? I have some understanding of higher order functions, but so far I've been unable to filter this successfully. Any pointers on how this could be achieved would be welcome, thanks.

struct MenuItems {
    var id: String
    var name: String

    init() {
        self.id = ""
        self.name = ""
    }
}

var m1 = MenuItems()
m1.id = "1"
m1.name = "Name 1"

var m2 = MenuItems()
m2.id = "2"
m2.name = "Name 2"

var m3 = MenuItems()
m3.id = "3"
m3.name = "Name 3"

var allMenuItems: [MenuItems] = [m1, m2, m3] // [{id "1", name "Name 1"}, {id "2", name "Name 2"}, {id "3", name "Name 3"}]

var anArrayOfIds: [String] = ["1", "3"]

The filtered output would be:

var filteredMenuItems: [MenuItems] = [m1, m3] // [{id "1", name "Name 1"}, {id "3", name "Name 3"}]

Any suggestions?

Upvotes: 1

Views: 129

Answers (4)

ielyamani
ielyamani

Reputation: 18581

You could do it like so:

let filteredMenuItems = allMenuItems.filter { anArrayOfIds.contains($0.id) }

I would suggest you :

  • remove the pointless initializer,
  • make id an integer,
  • if the properties won't be changed after initialization then use let instead of var,
  • make anArrayOfIds a set instead of an array, since the contains method would be O(1) instead of O(n).

Implementing all of these recommendations gives you the following code:

struct MenuItems {
    let id: Int
    let name: String
}

let m1 = MenuItems(id: 1, name: "Name 1")
let m2 = MenuItems(id: 2, name: "Name 2")
let m3 = MenuItems(id: 3, name: "Name 3")

let allMenuItems: [MenuItems] = [m1, m2, m3]

var aSetOfIds: Set<Int> = [1, 3]  //I used a var if aSetOfIds could be changed

var filteredMenuItems = allMenuItems.filter { aSetOfIds.contains($0.id) }

Upvotes: 2

pbodsk
pbodsk

Reputation: 6876

How about

let filteredMenuItems = allMenuItems.filter { anArrayOfIds.contains($0.id)}

That gives me the items with 1 and 3.

I've taken the liberty of updating your code a little:

struct MenuItems {
    let id: String
    let name: String
}

let m1 = MenuItems(id: "1", name: "Name 1")
let m2 = MenuItems(id: "2", name: "Name 2")
let m3 = MenuItems(id: "3", name: "Name 3")

let allMenuItems = [m1, m2, m3]
let anArrayOfIds: [String] = ["1", "3"]

let filteredMenuItems = allMenuItems.filter { anArrayOfIds.contains($0.id)}

Hope that helps

Upvotes: 2

vadian
vadian

Reputation: 285059

First of all please don't use a weird syntax in a struct like

init() {
     self.id = ""
     self.name = ""
}

Delete the init method and create items with the implicit memberwise initializer, by the way you should name structs representing a single object in singular form:

let m1 = MenuItem(id: "1", name: "Name 1")

You can even declare the members as constants

struct MenuItem {
    let id, name : String
}

And don't annotate types the compiler can infer.


Filter the array by another array of id values with

let filteredMenuItems = allMenuItems.filter{ anArrayOfIds.contains($0.id) }

Upvotes: 1

Joakim Danielson
Joakim Danielson

Reputation: 51861

You can use filter and contains

let filtered = allMenuItems.filter( { anArrayOfIds.contains($0.id) })

Upvotes: 1

Related Questions