【问题标题】:How to check if two arrays made from different structs have the same value?如何检查由不同结构组成的两个数组是否具有相同的值?
【发布时间】:2018-07-22 14:43:35
【问题描述】:

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

我尝试使用 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]”类型的操作数

我希望这一切都有意义。

提前致谢。

【问题讨论】:

  • 请在您的问题中包含OneStructTwoStruct 的声明。另外,我假设oneArray 的类型是[OneStruct] 其中twoArray[TwoStruct]?
  • 好的,给我一点时间来编辑 :D 没错,oneArray 是 OneStruct,twoArray 是 TwoStruct。
  • 我已经进行了这些更改,我要检查的两个相同的元素是 oneCategory 和 twoSubject。
  • @TMI 使它们成为一个结构并为比较参数实现 Eqauatble,我将编辑
  • 不,它们必须不同。除了类别和主题之外,它们根本不相关。

标签: arrays swift struct


【解决方案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 {


}

【讨论】:

  • 这将只允许两个实例,例如OneStruct 相互比较,但不会帮助将 OneStruct 的实例与 TwoStruct 进行比较。
  • 感谢您这么快回答,但如果它们的结构不相似怎么办?两者只有 1 点相似。
  • 请注意这里的Equatable一致性与两种不同类型之间的==比较运算符无关:符合Equatable(在这种情况下)只是提供synthesizing Equatable conformance OneStructTwoStruct 的成员恰好是 Equatable 自己。如果您将成员添加到例如OneStruct 不是 Equatable(例如一个虚拟的),你会注意到你会得到一个编译错误。
【解决方案2】:

对于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 类型的数组)中的一个成员,其等价类或双谓词成立。

/// 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 */

【讨论】:

  • 我也想到了协议,但是发现更改 lhs 或 rhs 要容易得多
猜你喜欢
  • 2014-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-30
  • 1970-01-01
  • 1970-01-01
  • 2011-09-07
  • 2021-12-01
相关资源
最近更新 更多