在swift中定位嵌套数组中数据的最佳方式



给定如下嵌套对象的数据:

struct Store{
var name: String
var items: [Item]
}

struct Item{
var name: String
var free: Bool
}

var dataSet = [
Store(name: "firstStore", items: [
Item(name: "item1", free: false), Item(name: "item2", free: false),   Item(name: "item3", free: true),
]),

Store(name: "secStore", items: [
Item(name: "item4", free: true), Item(name: "item5", free: false),   Item(name: "item6", free: true),
]),

Store(name: "thiStore", items: [
Item(name: "item7", free: false), Item(name: "item8", free: true),   Item(name: "item9", free: false),
]),

Store(name: "lastStore", items: [
Item(name: "item10", free: true), Item(name: "item11", free: false),   Item(name: "item12", free: true),
]),
]

通过给定一个部分(商店(和一行(项目(作为起点,我需要找到满足一些标准的下一个/上一个项目(在这种情况下是免费的(。我将使用IndexPath来标记位置。这些方法不仅应该返回项,还应该返回位置(用IndexPath表示(。

我得到了什么。它正在发挥作用,但肯定有一种更好、更干净的归档方式。

func nextFree(from start: IndexPath) -> (Item, IndexPath)?{
for (section, store) in dataSet.enumerated().dropFirst(start.section) {
for (row, item) in store.items.enumerated().filter({$0.element.free}){
if section == start.section && row <= start.row { continue }
return (item, IndexPath(row: row, section: section))
}
}
return nil
}

func previousFree(from start: IndexPath) -> (Item, IndexPath)?{
for (section, store) in dataSet.enumerated().reversed(){
if section > start.section { continue }
for (row, item) in store.items.enumerated().reversed().filter({$0.element.free}){
if section == start.section && row >= start.row { continue }
return (item, IndexPath(row: row, section: section))
}
}
return nil
}

做这件事最干净、最有表现力的方式是什么?

在Swift中,我们经常想使用所有花哨的功能,尽管利用mapfilterreducezip等超级有用的功能可能是个好主意。有时,简单的解决方案对给定的用例最有效。

这显然是一个非常有主见的答案,但这个问题需要这种性质的答案,所以这是我的。

我相信您使用简单的for-loop实现是正确的。这提高了可读性,并允许您在找到要查找的结果后快速返回。这是一个略有改进的版本,包含where子句。

func nextFree(from start: IndexPath) -> (Item, IndexPath)? {
let sections = dataSet.enumerated().dropFirst(start.section)
for (section, store) in sections {
let rows = store.items.enumerated().filter { $0.element.free }
for (row, item) in rows where section != start.section || row > start.row {
return (item, IndexPath(row: row, section: section))
}
}
return nil
}

前面提到的其他函数,如mapfilterreduce,不会给我们所需的灵活性,在这种情况下,简单的for-loop非常有用,易于理解。除了添加where子句之外,唯一的事情就是为正在迭代的枚举集合使用单独的属性,因为这将在读取每个代码生命周期时降低复杂性。

类似于nextFree,这里是previousFree函数:

func previousFree(from start: IndexPath) -> (Item, IndexPath)? {
let sectionsToDrop = (dataSet.count - 1) - start.section
let sections = dataSet.dropLast(sectionsToDrop).enumerated().reversed()
for (section, store) in sections {
let rows = store.items.enumerated().reversed().filter { $0.element.free }
for (row, item) in rows where section != start.section || row < start.row {
return (item, IndexPath(row: row, section: section))
}
}
return nil
}

最新更新