Swift 3 Equatable结构可选函数

Swift 3 Equatable结构可选函数,swift,Swift,这会有点啰嗦,请耐心听我说。我也是一个有点敏捷的初学者。我有一个定义了结构的数组 var modelOriginalArray = [model]() struct model: Equatable { var modelID = String() var modelName = String() var modelNumber = String() var manufacturer

这会有点啰嗦,请耐心听我说。我也是一个有点敏捷的初学者。我有一个定义了结构的数组

var modelOriginalArray                      = [model]()

struct model: Equatable  {
    var modelID         = String()
    var modelName       = String()
    var modelNumber     = String()
    var manufacturer    = String()
    var manufShort      = String()
    var phiTypeCode     = String()
    var phiTypeDesc     = String()


    init(modelID: String, modelName: String, modelNumber: String, manufacturer: String, manufShort: String, phiTypeCode: String, phiTypeDesc: String) {
        self.modelID        = modelID
        self.modelName      = modelName
        self.modelNumber    = modelNumber
        self.manufacturer   = manufacturer
        self.manufShort     = manufShort
        self.phiTypeCode    = phiTypeCode
        self.phiTypeDesc    = phiTypeDesc
    }

    static func == (lhs: model, rhs: model) -> Bool {
        return lhs.manufShort == rhs.manufShort && lhs.modelName == rhs.modelName && lhs.modelNumber == rhs.modelNumber
    }


}
我将大约5000条记录加载到此数组中。然后,我需要根据搜索条件筛选此数组。假设我正在寻找一家制造商“索尼”。索尼可能有多种型号,因此我需要将所有索尼唱片与更大的5000分开

    srchval = "SONY"
    var filteredArray = [model]()
    var uniqueFilteredArray = [model]()

    filteredArray = self.modelOriginalArray.filter { $0.manufShort.range(of: srchval, options: .caseInsensitive) != nil }
这将给我一个只有“索尼”唱片的阵列。但是,有些“索尼”记录可能在不同的modelID下有重复的manufShortmodelNamemodelNumber值。我需要把它们分开,只有唯一的记录

    // Find Uniquic options by removing duplicate Model Names
    uniqueFilteredArray = unique(models: filteredArray)


func unique(models: [model]) -> [model] {

    var uniqueModels = [model]()

    for model in models {
        if !uniqueModels.contains(model) {
            uniqueModels.append(model)
        }
    }

    return uniqueModels
}
这一切都很好。我遇到的问题是在筛选器中,在某些情况下,我必须确保记录匹配:

    static func == (lhs: model, rhs: model) -> Bool {
        return lhs.manufShort == rhs.manufShort && lhs.modelName == rhs.modelName && lhs.modelNumber == rhs.modelNumber
    }
在同一个班级的不同情况下,我只需要在手动短距离上进行匹配:

    static func == (lhs: model2, rhs: model2) -> Bool {
        return lhs.manufShort == rhs.manufShort
    }
我曾尝试创建一个单独的模型,即使用此不同的静态函数的model2,但我很难使用不同的结构将数据从一个数组移动到另一个数组

有什么想法或更好的方法来实现这一点


谢谢

您可以在
收藏
上使用以下扩展。没有测试

extension Collection where Iterator.Element: Equatable {
    func uniques(by equals: (Iterator.Element, Iterator.Element) -> Bool) -> [Iterator.Element] {
        var uniqueElems: [Iterator.Element] = []
        for elem in self {
            if uniqueElems.index(where: { equals($0, elem) }) == nil {
                uniqueElems.append(elem)
            }
        }
        return uniqueElems
    }   
}
然后你可以用

filteredArray.uniques { $0.manufShort == $1.manufShort }
filteredArray.uniques { $0.manufShort == $1.manufShort && $0.modelName == $1.modelName && $0.modelNumber == $1.modelNumber }

因为使用两种不同的方法来定义两个模型的“相等”,你可能应该考虑不使用<代码>=运算符,因为如果等式谓词不同,则不真正测试相等性。相反,您有两个不同的自定义谓词(适用于两个模型实例),希望在不同的上下文中使用。为什么不为此使用两个自定义类型(静态)方法,使用描述性名称,在语义上描述它们的不同含义

谢谢!这是很有意义的,我如何调用不同的(静态)方法,以便它能够根据我所追求的内容找到正确的函数。举个例子

设置示例:

struct Foo {
    let id: String
    let bar: Int
    let baz: Int
    let bax: Int
    init(_ id: String, _ bar: Int, _ baz: Int, _ bax: Int)
    {
        self.id = id
        self.bar = bar
        self.baz = baz
        self.bax = bax
    }

    static func byBarEqualityPredicate(lhs: Foo, rhs: Foo) -> Bool {
        return lhs.bar == rhs.bar 
    }

    static func byBazAndBaxEqualityPredicate(lhs: Foo, rhs: Foo) -> Bool {
        return lhs.baz == rhs.baz && lhs.bax == rhs.bax 
    }
}

let fooArr = [Foo("Foo A", 1, 2, 3),
              Foo("Foo B", 1, 1, 2),
              Foo("Foo C", 3, 1, 2)]
您的
unique
方法的一个稍加修改的版本,现在在
foos
数组中提供了一个
(Foo,Foo)->Bool
谓词:

func unique(foos: [Foo], predicate: (Foo, Foo) -> Bool) -> [Foo] {
    var uniqueFoos = [Foo]()
    for foo in foos {
        if !uniqueFoos.contains(where: { predicate($0, foo) }) {
            uniqueFoos.append(foo)
        }
    }
    return uniqueFoos
}
使用两个不同的
Foo
谓词进行测试:

// by 'bar' "equality": Foo A and Foo B will be considered "equal",
// and only Foo A, among these two , will be added to the "unique" array.
let fooWithBarPredicate = unique(foos: fooArr, predicate: Foo.byBarEqualityPredicate)
fooWithBarPredicate.forEach { print($0.id) } // Foo A, Foo C

// by 'baz' && 'bax' "equality": Foo A and Foo C will be considered "equal",
// and only Foo A, among these two, will be added to the "unique" array.
let fooWithBazBaxPredicate = unique(foos: fooArr, predicate: Foo.byBazAndBaxEqualityPredicate)
fooWithBazBaxPredicate.forEach { print($0.id) } // Foo A, Foo B

既然使用两种不同的方法来定义两个模型的“相等”,那么你可能应该考虑不使用=运算符,因为如果等式谓词不同,则不真正测试相等性。相反,您有两个不同的自定义谓词(适用于两个模型实例),希望在不同的上下文中使用。为什么不为此使用两个自定义类型(静态)方法,使用描述性名称,在语义上描述它们的不同含义?@dfri谢谢!这是很有意义的,我如何调用不同的(静态)方法,以便它能够根据我所追求的内容找到正确的函数。示例?当然,我添加了一个示例(
Foo
而不是
Model
,从示例的意义上来说:)。这对我来说非常有效。我甚至可以添加第三个谓词来进行更集中的搜索。完美的解决方案。