我有几个"任何"我要比较的值类型。
var any1: Any = 1
var any2: Any = 1
var any3: Any = "test"
var any4: Any = "test"
print(any1 == any2)
print(any2 == any3)
print(any3 == any4)
使用==运算符会显示错误:
"二元运算符' =='不适用于两个任何' (又名 '协议<>')操作数"
这样做的方法是什么?
答案 0 :(得分:22)
执行此操作的唯一方法是使用除==
之外的函数来获取类型参数,然后比较这些值是否属于该类型:
func isEqual<T: Equatable>(type: T.Type, a: Any, b: Any) -> Bool {
guard let a = a as? T, let b = b as? T else { return false }
return a == b
}
现在,使用上面的变量,你可以像这样比较它们:
var any1: Any = 1
var any2: Any = 1
var any3: Any = "test"
var any4: Any = "test"
isEqual(Int.self, a: any1, b: any2) // true
isEqual(Int.self, a: any2, b: any3) // false
isEqual(String.self, a: any3, b: any4) // true
答案 1 :(得分:3)
要使用==
运算符,键入必须符合Equatable
协议。 Any
协议不符合Equatable
协议,因此无法比较两个Any
值。这是合乎逻辑的 - Any
是一个过于宽泛的术语 - 价值观没有“共同点”。
更重要的是,Swift不允许比较具有不同类型的两个Equatable
值。例如。 Int
和String
都符合Equatable
但1 == "1"
无法编译。原因是在==
协议Equatable
中声明了func ==(lhs: Self, rhs: Self) -> Bool
:Self
。这个Self基本上意味着两个参数必须具有相同的类型。它是一种占位符 - 在特定类型的实现中,String user = pref.getString("user", default_user);
应该替换为此类型的名称。
答案 2 :(得分:3)
您可以使用AnyHashable
来做到这一点:
func equals(_ x : Any, _ y : Any) -> Bool {
guard x is AnyHashable else { return false }
guard y is AnyHashable else { return false }
return (x as! AnyHashable) == (y as! AnyHashable)
}
print("\(equals(3, 4))") // false
print("\(equals(3, equals))") // false
print("\(equals(3, 3))") // true
由于并非每个Equatable
都必须是Hashable
,所以在极少数情况下这可能会失败。
通常没有必要使用上述技巧;但有时您会需要它,就像有时需要AnyHashable
。
答案 3 :(得分:1)
您可以使用NSObject ...
var any1: Any = 1
var any2: Any = 1
var any3: Any = "test"
var any4: Any = "test"
var any5: Any? = nil
var any6: Any? = nil
print(any1 as? NSObject == any2 as? NSObject)
print(any2 as? NSObject == any3 as? NSObject)
print(any3 as? NSObject == any4 as? NSObject)
print(any4 as? NSObject == any5 as? NSObject)
print(any5 as? NSObject == any6 as? NSObject)
这应该产生:- 真正 假 真正 假 是
答案 4 :(得分:1)
亚伦·拉斯穆森(Aaron Rasmussen)的答案也可以用作扩展,例如:
public extension Equatable {
/// Equate two values of unknown type.
static func equate(_ any0: Any, _ any1: Any) -> Bool {
guard
let equatable0 = any0 as? Self,
let equatable1 = any1 as? Self
else { return false }
return equatable0 == equatable1
}
}
final class EquatableTestCase: XCTestCase {
func test_equate() {
let int: Any = Int.random( in: .min...(.max) )
let bool: Any = Bool.random()
XCTAssertTrue( Int.equate(int, int) )
XCTAssertTrue( .equate(bool, bool) )
XCTAssertFalse( .equate(int, int) )
XCTAssertTrue( AnyHashable.equate(bool, bool) )
XCTAssertFalse( AnyHashable.equate(bool, int) )
}
}
答案 5 :(得分:0)
我们可以通过以下方式解决
enum SwiftDataType
{
case String
case Int
case Int64
case Double
case Bool
case Undefined
}
func getType( of : Any ) -> SwiftDataType
{
if let type = of as? String
{
return SwiftDataType.String
}
else if let type = of as? Int
{
return SwiftDataType.Int
}
else if let type = of as? Int64
{
return SwiftDataType.Int64
}
else if let type = of as? Double
{
return SwiftDataType.Double
}
else if let type = of as? Bool
{
return SwiftDataType.Bool
}
else
{
return SwiftDataType.Undefined
}
}
func isEqual( a : Any, b : Any ) -> Bool
{
let aType : SwiftDataType = getType( of : a )
let bType : SwiftDataType = getType( of : b )
if aType != bType
{
print("Type is not Equal -> \(aType)")
return false
}
else
{
switch aType {
case SwiftDataType.String :
guard let aValue = a as? String, let bValue = b as? String else
{
return false
}
return aValue == bValue
case SwiftDataType.Int :
guard let aValue = a as? Int, let bValue = b as? Int else
{
return false
}
return aValue == bValue
case SwiftDataType.Int64 :
guard let aValue = a as? Int64, let bValue = b as? Int64 else
{
return false
}
return aValue == bValue
case SwiftDataType.Double :
guard let aValue = a as? Double, let bValue = b as? Double else
{
return false
}
return aValue == bValue
case SwiftDataType.Bool :
guard let aValue = a as? Bool, let bValue = b as? Bool else
{
return false
}
return aValue == bValue
default:
return false
}
}
}