Swift 4 - 使用数组过滤数组

6

我有一个条目列表,每个条目都有一个id,我想将它们过滤掉只剩下与selectedIDs中的某个id匹配的entry.id。能否使用filter方法实现这一点,还是必须使用for循环?

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个回答

6

Rakesha Shastri的回答没有任何问题。出于性能方面的考虑,您可能希望将selectedIDsArray更改为Set

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) })

原因在于搜索一个Array的计算复杂度为O(n),其中n是数组的长度,而搜索一个Set(即哈希表)的平均计算复杂度为O(1)
  • 如果将selectedIDs保持为数组,则整体解决方案的复杂度为O(n * m),其中nm分别是selectedIDsallEntries的长度。
  • 如果使用Set,则整体复杂度降至O(m)
话虽如此,对于你的示例来说,这两种方法都太简单了,没有什么区别。

4

根据 selectedIDs 是否包含 id,筛选所有条目 allEntries

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) })

谢谢。出于好奇,如果说 selectedIDs 是另一种包含 ID 属性的结构体类型,那么这将如何改变 selectedIDs.contains($0.id) 这部分呢? - user3628240
map then filter - Ashley Mills
@user3628240 像Ashley说的那样,你可以将结构体数组映射到字符串数组,然后进行过滤。 - Rakesha Shastri
Contains(where:) 更为恰当。 - ielyamani

1
你可以使用 map(:)filter(:) 来实现这个。
let matchingEntries = allEntries.map({$0.id}).filter({selectedIDs.contains($0)})

.map 将会返回一个 id 数组,然后 .filter 会用 selectedIDs 对它们进行过滤。


1

Swift 5.5:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接