如何检查由不同结构构成的两个数组是否具有相同的值?

时间:2018-07-22 14:43:36

标签: arrays swift struct

我有两个由不同结构构成的数组,并且它们在数组的不同位置都具有相同的信息。

我尝试使用if语句进行两次for-in循环,以检查它们是否具有相同的值,但是我在其他语言(如PHP)中执行此操作的方式无效。

请帮助我,这是到目前为止我得到的:

单个文件

struct oneStruct {
    var oneTitle: String
    var onePic: UIImage?
    var oneCategory: String
}

class OneSingleton {
    static let sharedInstance = OneSingleton()
    private init() {}
    var oneArray: [OneStruct] = [//you get the gist, this is full of array stuff]
}

两个文件

struct TwoStruct {
    var twoName: String
    var twoPic: UIImage?
    var twoSubject: String
    var twoStuff1: String
    // etc. I can't get into much more here, sorry.
}

class TwoSingleton {
    static let sharedInstance = TwoSingleton()
    private init() {}
    var twoArray: [TwoStruct] = [//you get the gist, this is full of array stuff as well]
}

视图控制器

//the singleton stuff is needed

var oneArray = [OneSingleton.sharedInstance.oneArray]
var twoArray = [TwoSingleton.sharedInstance.twoArray]
var filterArray: [TwoStruct] = []

override func viewDidLoad() {
    super.viewDidLoad()

    for two in twoArray {
        for one in oneArray {
            if two == one {
                filterArray.append(contentsOf: two)
            }
        }
    }
}

这给了我一个编译错误

  

二进制运算符'=='不能应用于类型'[TwoStruct]'和'[OneStruct]'的操作数

我希望这一切都有道理。

谢谢。

2 个答案:

答案 0 :(得分:-1)

比较两者的实现Equatable并将lhs或rhs更改为另一个对象

struct OneStruct :Equatable {

    var value1: String
    var value2: UIImage? /// image comparsion is not an easy way you may add id of image
    var value3: String

   // also you can omit any static method part from any class 

    static func ==(lhs: TwoStruct, rhs: OneStruct) -> Bool {
        return lhs.value1 == rhs.value1 && lhs.value3 == rhs.value3
    }

}

struct TwoStruct :Equatable {

    var value1: String
    var value2: UIImage? /// image comparsion is not an easy way you may add id of image
    var value3: String

    // also you can omit any static method part from any class 

    static func ==(lhs: OneStruct, rhs: TwoStruct) -> Bool {
        return lhs.value1 == rhs.value1 && lhs.value3 == rhs.value3
    }
 }    

//

let s1 = OneStruct(value1: "", value2: UIImage.init(named: ""), value3: "")
let s2 = TwoStruct(value1: "", value2: UIImage.init(named: ""), value3: "")

if s1 == s2 {


}

答案 1 :(得分:-1)

对于每个OneStructTwoStruct类型,您似乎都有一个要用于比较的属性。 categorysubject。因此,首先,为这两个属性设计两个协议的蓝图:

protocol Categorizable {
    var category: String { get }
}

protocol Subjectable {
    var subject: String { get }
}

就本示例而言,OneStructTwoStruct的最少示例将分别符合CategorizableSubjectable

struct OneStruct: Categorizable {
    var category: String
    init(_ category: String) { self.category = category }
}

struct TwoStruct: Subjectable {
    var subject: String
    init(_ subject: String) { self.subject = subject }
}

现在,当比较两种不同类型时,我们真的不想谈论平等,而是可以比较这两种类型的实例的等效类或双向谓词。因此,让我们定义例如一个双向谓词,可用于比较分别符合CategorizableSubjectable的两个实例:

struct BiPredicate<T: Categorizable, U: Subjectable> {
    static func compare(_ lhs: T, _ rhs: U) -> Bool {
        return lhs.category == rhs.subject
    }
    static func compare(_ lhs: U, _ rhs: T) -> Bool {
        return compare(rhs, lhs)
    }
}

根据您自己的示例代码,似乎您希望两个过滤器分别基于是否对TwoStruct数组(即符合Subjectable的类型的数组)进行过滤,数组,在OneStruct数组(即符合Categorizable的类型的数组)中存在一个成员,对于该成员,等效类或双向谓词为true。

/// Returns `lhs` argument filtered based on its BiPredicate intersection
/// with the `rhs` argument.
/// Time complexity: O(n^2)
func filterByIntersect<T: Subjectable, U: Categorizable>(_ lhs: [T], over rhs: [U]) -> [T] {
    return lhs.filter { l in rhs.contains { r in BiPredicate.compare(l, r) } }
}

我们可以将其用作:

let oneArray = [OneStruct("foo"), OneStruct("bar"), OneStruct("baz"), OneStruct("bax")]
let twoArray = [TwoStruct("baxx"), TwoStruct("foo"), TwoStruct("bax")]

let result = filterByIntersect(twoArray, over: oneArray)
for twoElement in result { print(twoElement.subject) } /* foo
                                                          bax */

现在,这主要是一个有趣的练习,但是最后却得到了很多样板代码,这些代码本来应该是一个简单的任务。您总是可以删除泛型,而只需使用一个简单的函数来测试OneStructTwoStruct上的单个等效类:

func compareCategoryWithSubject(_ lhs: OneStruct, _ rhs: TwoStruct) -> Bool {
    return lhs.category == rhs.subject
}

/// Returns `lhs` argument filtered based on intersection over comparing 
/// the `subject` properties of the elements of `lhs` with the `category`
/// properties of the elements of `rhs`.
/// Time complexity: O(n^2)
func filterByIntersect(_ lhs: [TwoStruct], over rhs: [OneStruct]) -> [TwoStruct] {
    return lhs.filter { l in rhs.contains { r in
        compareCategoryWithSubject(r, l) } }
}

或者,对于一种可能甚至更简单且渐近地更高效的方法,请将所有逻辑放入filterByIntersect(...)函数中:

/// Returns `lhs` argument filtered based on intersection over comparing
/// the `subject` properties of the elements of `lhs` with the `category`
/// properties of the elements of `rhs`.
/// Time complexity: O(n) [contains(_:) is O(1) for Set)
func filterByIntersect(_ lhs: [TwoStruct], over rhs: [OneStruct]) -> [TwoStruct] {
    let rhsCategories = Set(rhs.map { $0.category })
    return lhs.filter { l in rhsCategories.contains(l.subject) }
}

以上两种方法均产生与上述相同的结果:

let oneArray = [OneStruct("foo"), OneStruct("bar"), OneStruct("baz"), OneStruct("bax")]
let twoArray = [TwoStruct("baxx"), TwoStruct("foo"), TwoStruct("bax")]

let result = filterByIntersect(twoArray, over: oneArray)
for twoElement in result { print(twoElement.subject) } /* foo
                                                          bax */