Проверка содержимого массива на значения, определенные как Any, но гарантированно одного типа.

Основываясь на этом моем вопросе (и принятом ответе), я хочу проверить наличие значения в массиве.

Значение хранится в переменной, определенной как тип Anyи массив определяется как [Any],

Фактические типы значения, хранящегося в переменной и элементах в массиве, определяются во время выполнения, но гарантированно удовлетворяют следующим условиям:

  1. Оба типа (переменные и элементы массива) совпадают, и
  2. Они либо один из String, Int или же Bool,

Пока что у меня работает этот код:

var isContained = false

if let intValue = anyValue as? Int {
    isContained = arrayOfAny.contains({element in return ((element as? Int) == intValue)})
}
else if let stringValue = anyValue as? String {
    isContained = arrayOfAny.contains({element in return ((element as? String) == stringValue)})
}
else if let boolValue = anyValue as? Bool {
    isContained = arrayOfAny.contains({element in return ((element as? Bool) == boolValue)})
}

Тем не менее, есть много логического дублирования, и я хотел бы сделать его умнее, возможно, что-то вроде этого:

isContained = arrayOfAny.contains({element in 
    return ((element as? Equatable) == (anyValue as? Equatable))
})

... но ограничения на использование протокола Equatable стоять на пути. Любой совет?

1 ответ

Решение

Теперь я вижу, что вы пытаетесь сделать. Вот пример того, как вы можете заставить его работать

let arrayOfAny:[AnyObject] = [1,7,9,true, "string"]
func getAny(value:AnyObject) -> [AnyObject]{
    return self.arrayOfAny.filter ({$0 === value})
}

Вышеприведенная функция вернет массив совпадений, который в идеале должен быть единственным результатом или пустым массивом.

Пример:

self.getAny(1) // [1]
self.getAny(0) // []

Вы также можете изменить его, чтобы просто вернуть Bool

func getAny(value:AnyObject) -> Bool{
  return self.arrayOfAny.filter ({$0 === value}).count > 0
}

Пример:

self.getAny(1) // true
self.getAny(0) // false

Редактировать:

Как отметил Мартин Р, это не всегда будет работать. К сожалению, я не полностью проверил это, прежде чем опубликовать этот ответ. Поработав с этим некоторое время, я придумал очень похожий подход, который есть у NicolasMiari:

let arrayOfAny:[AnyObject] = [1,Int.max,9,true, "string"]
func getAny(anyValue:AnyObject) -> [AnyObject]{
    return self.arrayOfAny.filter ({
         var exist:Bool
         switch anyValue.self{
            case is String: exist = $0 as? String == anyValue as? String
                break
            case is Int: exist = $0 as? Int == anyValue as? Int
                break
            case is Bool: exist = $0 as? Bool == anyValue as? Bool
                break
            default: exist = false
            }
            return exist
     })

}

Недостатком этого подхода является то, что int 1 а также true будет возвращено при звонке self.getAny(1) результат будет [1,1] как 1 а также true может быть успешно приведен к обоим Int а также Bool и не так, как вероятно, намеревался просто вернуться [1], Другими словами, если у вас просто есть true в вашем массиве, не имея Int 1 вы все равно получите положительный результат, как если бы он существовал в вашем массиве. То же самое работает и наоборот.

Другие вопросы по тегам