我有两个这样的数组的多组。我正在从第三方得到它们。
var array1 : [Any?]
var array2 : [Any?]我知道这些数组中对象的类型(在编译时)。例如,第一个元素是String,第二个是Int。
我目前比较了每一组这样的数组(请注意,数组并不是同构的)。
array1[0] as? String == array2[0] as? String
array1[1] as? Int == array2[1] as? Int
...最大的问题是每个集合都有不同的类型。因此,我假设有10组数组,每个数组有5个元素。我必须对特定类型和比较进行10*5的显式转换。
我希望能够编写一个通用的方法,可以比较两个这样的数组(不需要指定所有类型)
compareFunc(array1, array2)我开始沿着这条路走。然而,我想不出我也应该转换什么对象。我试过Equatable了。然而,swift不喜欢直接使用它。所以,像这样的东西是行不通的
func compare(array1: [Any?], array2: [Any?]) {
for index in 0..<array1.count {
if (array1[index] as? Equatable != array2[index] as? Equatable) {
// Do something
}
}
}此数组中的每个对象都将是可相等的。但是,我不确定在这种情况下如何使用它。
发布于 2016-05-20 04:02:18
基于(尝试)到已知元素类型的类型转换,构造一个简单的逐个元素比较函数
由于您的目标是比较(可选) Any元素的数组,您可以通过使用switch块尝试将数组的元素向下转换为您的“第三方数组”中的不同已知类型,来构造一个函数来执行逐个元素的比较。请注意,您不需要指定对应于特定类型的元素位置(因为这在不同的数组集合中可能不同),只需指定任何给定元素可能属于的不同类型的详尽集合。
下面是这样一个函数的示例:
func compareAnyArrays(arr1: [Any?], _ arr2: [Any?]) -> Bool {
/* element-by-element downcasting (to known types) followed by comparison */
return arr1.count == arr2.count && !zip(arr1, arr2).contains {
/* note that a 'true' below indicates the arrays differ (i.e., 'false' w.r.t. array equality) */
if let v1 = $1 {
/* type check for known types */
switch $0 {
case .None: return true
case let v0 as String:
if let v1 = v1 as? String { return !(v0 == v1) }; return true
case let v0 as Int:
if let v1 = v1 as? Int { return !(v0 == v1) }; return true
/* ...
expand with the known possible types of your array elements
... */
case _ : return true
/* */
}
}
else if let _ = $0 { return true }
return false
}
}或者,也可以通过使用compare(...) helper function from @Roman Sausarnes:s answer (稍微修改一下)使switch块不那么臃肿
func compareAnyArrays(arr1: [Any?], _ arr2: [Any?]) -> Bool {
/* modified helper function from @Roman Sausarnes:s answer */
func compare<T: Equatable>(obj1: T, _ obj2: Any) -> Bool {
return obj1 == obj2 as? T
}
/* element-by-element downcasting (to known types) followed by comparison */
return arr1.count == arr2.count && !zip(arr1, arr2).contains {
/* note also that a 'true' below indicates the arrays differ
(=> false w.r.t. equality) */
if let v1 = $1 {
/* type check for known types */
switch $0 {
case .None: return true
case let v0 as String: return !compare(v0, v1)
case let v0 as Int: return !compare(v0, v1)
/* ...
expand with the known possible types of your array elements
... */
case _ : return true
/* */
}
}
else if let _ = $0 { return true }
return false
}
}示例用法:
/* Example usage #1 */
let ex1_arr1 : [Any?] = ["foo", nil, 3, "bar"]
let ex1_arr2 : [Any?] = ["foo", nil, 3, "bar"]
compareAnyArrays(ex1_arr1, ex1_arr2) // true
/* Example usage #2 */
let ex2_arr1 : [Any?] = ["foo", nil, 2, "bar"]
let ex2_arr2 : [Any?] = ["foo", 3, 2, "bar"]
compareAnyArrays(ex2_arr1, ex2_arr2) // false发布于 2016-05-20 02:27:31
这是一个边际解决方案,但它应该会减少您试图避免的一些重复代码:
func compareAnyArray(a1: [Any?], _ a2: [Any?]) -> Bool {
// A helper function for casting and comparing.
func compare<T: Equatable>(obj1: Any, _ obj2: Any, t: T.Type) -> Bool {
return obj1 as? T == obj2 as? T
}
guard a1.count == a2.count else { return false }
return a1.indices.reduce(true) {
guard let _a1 = a1[$1], let _a2 = a2[$1] else { return $0 && a1[$1] == nil && a2[$1] == nil }
switch $1 {
// Add a case statement for each index in the array:
case 0:
return $0 && compare(_a1, _a2, t: Int.self)
case 1:
return $0 && compare(_a1, _a2, t: String.self)
default:
return false
}
}
}这不是最好的解决方案,但它将减少您必须编写的代码量,并且它应该适用于任何两个[Any?],只要您知道索引0处的类型是Int,而索引1处的类型是String,依此类推……
发布于 2019-09-02 17:14:30
一个紧凑的Swift 5版本的Aaron Rasmussen的伟大解决方案:
func compare(a1: [Any?], a2: [Any?]) -> Bool {
guard a1.count == a2.count else { return false }
func compare<T: Equatable>(obj1: Any, _ obj2: Any, t: T.Type) -> Bool {
return obj1 as? T == obj2 as? T
}
return a1.indices.reduce(true) {
guard let _a1 = a1[$1], let _a2 = a2[$1] else { return $0 && a1[$1] == nil && a2[$1] == nil }
switch $1 {
case 0: return $0 && compare(obj1: _a1, _a2, t: Int.self)
case 1: return $0 && compare(obj1: _a1, _a2, t: String.self)
case 2: return $0 && compare(obj1: _a1, _a2, t: <#TypeOfObjectAtIndex2#>.self)
default: return false
}
}
}https://stackoverflow.com/questions/37328030
复制相似问题