6

I have a list of entries, that have an id, and I want to filter them down to ones that have an entry.id matching one of the ids in selectedIDs. Is there a way to do this with filter or do I have to use a for loop?

struct Entry {
    let id: String
}
var allEntries = [Entry]()
var selectedIDs = [String]

e.g.

allEntries = [Entry(id: "1"), Entry(id:"2"), Entry(id:"3"), Entry(id:"4")]
selectedIDs = ["1", "3"]

// return selectedEntries
var selectedEntries = [Entry(id: "1"), Entry(id: "3")]

4 Answers 4

7

There's nothing wrong with Rakesha Shastri's answer. For performance reasons, you may want to make selectedIDs a Set instead of an Array:

let allEntries = [Entry(id: "1"), Entry(id:"2"), Entry(id:"3"), Entry(id:"4")]
let selectedIDs: Set<String> = ["1", "3"]
let selectedEntries = allEntries.filter({ selectedIDs.contains($0.id) })

The reason is that searching an Array has a computational complexity of O(n) where n is the length of the array, while searching a Set (i.e. a hash table) is O(1) on average.

  • If you keep selectedIDs as array, the overall solution has a complexity of O(n * m) where n and m are the lengths of selectedIDs and allEntries, respectively.

  • If you use Set, the overall complexity reduces to O(m).

Having said that, your example is too trivial for either methods to make a difference.

Sign up to request clarification or add additional context in comments.

Comments

4

Filter allEntries based on whether selectedIDs contains id.

var allEntries = [Entry(id: "1"), Entry(id:"2"), Entry(id:"3"), Entry(id:"4")]
var selectedIDs = ["1", "3"]

var selectedEntries = allEntries.filter({ selectedIDs.contains($0.id) })

4 Comments

Thank you. Out of curiosity, if say selectedIDs were another type of struct with IDs as a property, how would this change the selectedIDs.contains($0.id) part?
map then filter
@user3628240 like Ashley said, you map the struct array to a string array and then do the filtering.
Contains(where:) would be more appropriate developer.apple.com/documentation/swift/array/2297359-contains
1

You can use map(:) and filter(:) to achieve this

let matchingEntries = allEntries.map({$0.id}).filter({selectedIDs.contains($0)})

.map will return you just id's as an array, then .filter will filter them with the selectedIDs

Comments

1

Swift 5.5:

let filteredArray = array.filter { self.selectedIDs.map(\.id).contains($0.id) }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.