这将是一个有点长的啰嗦,所以请耐心等待。我也是一个快速的初学者。我有一个定义了struct的数组。
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 下有重复的 manufShort , modelName , modelNumber 值。我需要将它们分开并且只有独特的记录。
// 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
}
在同一课程的不同情况下,我只需要匹配 manufShort :
static func == (lhs: model2, rhs: model2) -> Bool {
return lhs.manufShort == rhs.manufShort
}
我尝试使用这个不同的静态函数创建一个单独的模型,即model2,但是我很难将数据从一个数组移动到另一个数组,并且具有不同的结构。
有任何想法或更好的方法来实现这一目标吗?
由于
答案 0 :(得分:0)
您可以在Collection
上使用以下扩展程序。未经测试。
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 }
答案 1 :(得分:0)
由于您使用两种不同的方法来定义"相等"在两个模型中,您可能应该考虑不使用==
运算符,因为如果等式谓词因具体情况而异,则您不会真正测试相等性。相反,您有两个不同的自定义谓词(适用于两个模型实例),您希望在不同的上下文中使用它们。为什么不使用两个自定义类型(静态)方法,使用描述性名称,从语义上描述它们的不同含义?
谢谢!这很有意义,我如何调用不同的(静态)方法,以便根据我所追求的内容找到正确的函数。一个例子?
示例设置:
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
方法的略微修改版本,现在在(Foo, Foo) -> Bool
数组中提供foos
谓词:
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