过滤数据模型数组

时间:2018-01-17 18:22:27

标签: ios swift sorting data-structures enums

我有一个包含结构数组的数据模型。我正在使用它来填充tableView。效果很好,但我需要帮助过滤数据。

我希望能够通过extremeSport枚举进行过滤(通过按下UI中的按钮。)在下面的示例中,有3个运动有8个技巧。最终,将有大约10项运动和150-200技巧(可能更多的技巧。)过滤在这里是有道理的。

问题是我不知道如何从Sections转到ExtremeModel,因此我可以通过extremeSport进行过滤。我得到的最接近的是按sectionName字母排序。

struct ExtremeModel {
    let trick: String
    let definition: String
    let extremeSport: Sport
    enum Sport {
        case bmx
        case skateboarding
        case snowboarding
    }
}
struct Sections {
    let sectionName: String
    let Objects: [ExtremeModel]
}

struct Data {
    static func allTricks() -> [Sections] {
        return [
            Sections(sectionName: "A", Objects: [
                ExtremeModel(trick: "Acid Drop", definition: "Lorem ipsum", extremeSport: .skateboarding),
                ExtremeModel(trick: "Axel Stall", definition: "Lorem ipsum", extremeSport: .skateboarding)
            ]),
            Sections(sectionName: "B", Objects: [
                ExtremeModel(trick: "Back Flip", definition: "Lorem ipsum", extremeSport: .snowboarding),
                ExtremeModel(trick: "Bar Spin", definition: "Lorem ipsum", extremeSport: .bmx),
                ExtremeModel(trick: "Bunny Hop", definition: "Lorem ipsum", extremeSport: .bmx)
            ]),
            Sections(sectionName: "S", Objects: [
                ExtremeModel(trick: "Shifty", definition: "Lorem ipsum", extremeSport: .snowboarding),
                ExtremeModel(trick: "Shuvit", definition: "Lorem ipsum", extremeSport: .skateboarding),
                ExtremeModel(trick: "Stalefish", definition: "Lorem ipsum", extremeSport: .snowboarding)
            ]),
        ]
    }
}

用法。这是我在排序时遇到麻烦的地方。

let allTerms = Data.allTricks()

// Here, I am filtering by Section Name. I want to filter by extremeSport, so I can update the view based on sports.
let filteredSports = allTerms.filter { (sport:Sections) -> Bool in
    return sport.sectionName == "A"
}

如何通过extremeSport枚举过滤allTricks()数据?

2 个答案:

答案 0 :(得分:2)

我会稍微修改你的模型。我建议您使用Dictionary而不是Array,这样您就可以更自然地找到您感兴趣的技巧。

enum ExtremeSport {
    case bmx
    case skateboarding
    case snowboarding
}

struct ExtremeSportTrick {
    let name: String
    let definition: String
    let extremeSport: ExtremeSport
}


struct SportData {
    static let allTricks = [
        ExtremeSportTrick(name: "Acid Drop", definition: "Lorem ipsum", extremeSport: .skateboarding),
        ExtremeSportTrick(name: "Axel Stall", definition: "Lorem ipsum", extremeSport: .skateboarding),
        ExtremeSportTrick(name: "Back Flip", definition: "Lorem ipsum", extremeSport: .snowboarding),
        ExtremeSportTrick(name: "Bar Spin", definition: "Lorem ipsum", extremeSport: .bmx),
        ExtremeSportTrick(name: "Bunny Hop", definition: "Lorem ipsum", extremeSport: .bmx),
        ExtremeSportTrick(name: "Shifty", definition: "Lorem ipsum", extremeSport: .snowboarding),
        ExtremeSportTrick(name: "Shuvit", definition: "Lorem ipsum", extremeSport: .skateboarding),
        ExtremeSportTrick(name: "Stalefish", definition: "Lorem ipsum", extremeSport: .snowboarding)
    ]

    static func allTricksByFirstLetter() -> [String: [ExtremeSportTrick]] {
        return Dictionary(grouping: allTricks, by: { String($0.name.first!) })
    }

    static func allTricksBySport() -> [ExtremeSport: [ExtremeSportTrick]] {
        return Dictionary(grouping: allTricks, by: { $0.extremeSport })
    }
}

使用示例:

extension Dictionary {
    func prettyString<T>() -> String where Dictionary.Value == [T] {
        return Array(self)
            .map{ key, values in """
            \(key): [
                \(values.map{ "\($0)" }.joined(separator: ",\n\t"))
            ]
            """ }
            .joined(separator: ",\n")
    }
}

let allTricksBySport = SportData.allTricksBySport()
let allTricksByFirstLetter = SportData.allTricksByFirstLetter()
let allBMXTricks = allTricksBySport[.bmx]
let allATricks = SportData.allTricksByFirstLetter()["A"]

print("=== All tricks by sport:")
print(allTricksBySport.prettyString())
print("\n\n\n=== All tricks by first letter:")
print(allTricksByFirstLetter.prettyString())
print("\n\n\n=== All bmx tricks:")
print(allBMXTricks!.map{ "\($0)"}.joined(separator: ",\n"))
print("\n\n\n=== All tricks whose name starts with \"A\":")
print(allATricks!.map{ "\($0)"}.joined(separator: ",\n"))

结果:

=== All tricks by sport:
snowboarding: [
    ExtremeSportTrick(name: "Back Flip", definition: "Lorem ipsum", extremeSport: Untitled.ExtremeSport.snowboarding),
    ExtremeSportTrick(name: "Shifty", definition: "Lorem ipsum", extremeSport: Untitled.ExtremeSport.snowboarding),
    ExtremeSportTrick(name: "Stalefish", definition: "Lorem ipsum", extremeSport: Untitled.ExtremeSport.snowboarding)
],
bmx: [
    ExtremeSportTrick(name: "Bar Spin", definition: "Lorem ipsum", extremeSport: Untitled.ExtremeSport.bmx),
    ExtremeSportTrick(name: "Bunny Hop", definition: "Lorem ipsum", extremeSport: Untitled.ExtremeSport.bmx)
],
skateboarding: [
    ExtremeSportTrick(name: "Acid Drop", definition: "Lorem ipsum", extremeSport: Untitled.ExtremeSport.skateboarding),
    ExtremeSportTrick(name: "Axel Stall", definition: "Lorem ipsum", extremeSport: Untitled.ExtremeSport.skateboarding),
    ExtremeSportTrick(name: "Shuvit", definition: "Lorem ipsum", extremeSport: Untitled.ExtremeSport.skateboarding)
]



=== All tricks by first letter:
B: [
    ExtremeSportTrick(name: "Back Flip", definition: "Lorem ipsum", extremeSport: Untitled.ExtremeSport.snowboarding),
    ExtremeSportTrick(name: "Bar Spin", definition: "Lorem ipsum", extremeSport: Untitled.ExtremeSport.bmx),
    ExtremeSportTrick(name: "Bunny Hop", definition: "Lorem ipsum", extremeSport: Untitled.ExtremeSport.bmx)
],
A: [
    ExtremeSportTrick(name: "Acid Drop", definition: "Lorem ipsum", extremeSport: Untitled.ExtremeSport.skateboarding),
    ExtremeSportTrick(name: "Axel Stall", definition: "Lorem ipsum", extremeSport: Untitled.ExtremeSport.skateboarding)
],
S: [
    ExtremeSportTrick(name: "Shifty", definition: "Lorem ipsum", extremeSport: Untitled.ExtremeSport.snowboarding),
    ExtremeSportTrick(name: "Shuvit", definition: "Lorem ipsum", extremeSport: Untitled.ExtremeSport.skateboarding),
    ExtremeSportTrick(name: "Stalefish", definition: "Lorem ipsum", extremeSport: Untitled.ExtremeSport.snowboarding)
]



=== All bmx tricks:
ExtremeSportTrick(name: "Bar Spin", definition: "Lorem ipsum", extremeSport: Untitled.ExtremeSport.bmx),
ExtremeSportTrick(name: "Bunny Hop", definition: "Lorem ipsum", extremeSport: Untitled.ExtremeSport.bmx)



=== All tricks whose name starts with "A":
ExtremeSportTrick(name: "Acid Drop", definition: "Lorem ipsum", extremeSport: Untitled.ExtremeSport.skateboarding),
ExtremeSportTrick(name: "Axel Stall", definition: "Lorem ipsum", extremeSport: Untitled.ExtremeSport.skateboarding)

根据您对可变性的需求,这些数组的大小/数量等等,您可能希望使用lazy var来实现allTricksByFirstLetterallTricksBySport

答案 1 :(得分:1)

前面有几个人指出:

  • 正如@Alexander所提到的,您应该考虑构建数据的最佳方法。我的答案涉及对代码进行的最小程度的更改......想一想这是否合适。
  • 按惯例,结构名称是单数。

我认为这是你正在尝试做的事情:

struct ExtremeModel {
    var trick: String!
    var definition: String!
    var extremeSport: Sport!
    enum Sport {
        case bmx
        case skateboarding
        case snowboarding
    }
}

// Struct names should be singular!
struct Section {
    var sectionName: String!
    var Objects: [ExtremeModel]!
}

// Renamed to avoid collision with Foundation's Data class
struct MyData {
    static func allTricks() -> [Section] {
        return [
            Section(sectionName: "A", Objects: [
                ExtremeModel(trick: "Acid Drop", definition: "Lorem ipsum", extremeSport: .skateboarding),
                ExtremeModel(trick: "Axel Stall", definition: "Lorem ipsum", extremeSport: .skateboarding)
                ]),
            Section(sectionName: "B", Objects: [
                ExtremeModel(trick: "Back Flip", definition: "Lorem ipsum", extremeSport: .snowboarding),
                ExtremeModel(trick: "Bar Spin", definition: "Lorem ipsum", extremeSport: .bmx),
                ExtremeModel(trick: "Bunny Hop", definition: "Lorem ipsum", extremeSport: .bmx)
                ]),
            Section(sectionName: "S", Objects: [
                ExtremeModel(trick: "Shifty", definition: "Lorem ipsum", extremeSport: .snowboarding),
                ExtremeModel(trick: "Shuvit", definition: "Lorem ipsum", extremeSport: .skateboarding),
                ExtremeModel(trick: "Stalefish", definition: "Lorem ipsum", extremeSport: .snowboarding)
                ]),
        ]
    }
}

let allTricks = MyData.allTricks()

let filteredSports = allTricks.filter { (section) -> Bool in
    return section.Objects.contains(where: { (extremeModel) -> Bool in
        return extremeModel.extremeSport == .skateboarding
    })
}

print(filteredSports.count)