arrays - 如何检查由不同结构组成的两个数组是否具有相同的值?
问题描述
我有两个由不同结构组成的数组,它们在数组的不同位置都有相同的信息。
我尝试使用 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]”类型的操作数
我希望这一切都有意义。
提前致谢。
解决方案
It seems you have, for each of your types OneStruct
and TwoStruct
, one respective property that you would like to use for comparison; category
and subject
, respectively. So to start out, lets blueprint two protocols for these two properties:
protocol Categorizable {
var category: String { get }
}
protocol Subjectable {
var subject: String { get }
}
For the purpose of this example, minimal examples of OneStruct
and TwoStruct
would then conform to Categorizable
and Subjectable
, respectively:
struct OneStruct: Categorizable {
var category: String
init(_ category: String) { self.category = category }
}
struct TwoStruct: Subjectable {
var subject: String
init(_ subject: String) { self.subject = subject }
}
Now, we don't really want to talk about equality when comparing two different types, rather equivalent classes or bi-predicates over which instances of these two types can be compared. So let's define e.g. a bi-predicate that can be used to compare two instances conforming to Categorizable
and Subjectable
, respectively:
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)
}
}
Based on your own example code, it seems that you want two filter an array of TwoStruct
(namely, an array of a type conforming to Subjectable
) based on whether, for each element in the array, there exist a member in an array of OneStruct
(namely, an array of a type conforming to Categorizable
) for which the equivalent class or bi-predicate holds 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) } }
}
Which we may use as:
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 */
Now, this was mostly a somewhat interesting exercise, but in the end ended up in quite a lot of boilerplate code for something that should be quite a simple task. You could always drop the generics and just go with a simple function for testing a single equivalent class over OneStruct
and TwoStruct
:
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) } }
}
Or, for a possibly even simple and also asymptotically more performant approach, placing all the logic into the filterByIntersect(...)
function:
/// 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) }
}
Both the above yielding the same result as above:
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 */
推荐阅读
- javascript - 如何使用解构来获取参数的目标属性
- python - 无法导入模块“lambda_function”:没有名为“cx_Oracle”的模块
- swift - 为什么在 Data.base64EncodedString 中使用 endLineWithLineFeed 不会在编码字符串的末尾添加新行?
- xpath - 在与 Xpath 保持关系的同时提取信息
- python - model.set_weights(model.get_weights()) 返回错误
- c# - 为什么使等待同步不能在单独的方法中工作?
- amazon-dynamodb - 使用硬编码散列键但使用不同范围键输入的行
- graph - 计算从给定顶点到具有定义属性的顶点的最短距离
- java - Seleniumchrome 驱动程序无法打开
- php - 在 rest API (php) 中调用 LINK