Подтвердить что ты не робот

Определите, содержит ли диапазон значение

Я пытаюсь найти способ определить, попадает ли значение в Range в Swift.

В основном то, что я пытаюсь сделать, это адаптировать один из примеров инструкции switch, чтобы сделать что-то вроде этого:

let point = (1, -1)
switch point {
case let (x, y) where (0..5).contains(x):
    println("(\(x), \(y)) has an x val between 0 and 5.")
default:
    println("This point has an x val outside 0 and 5.")
}

Насколько я могу судить, нет никакого встроенного способа сделать то, что делает мой воображаемый метод .contains.

Итак, я попытался расширить класс Range. Однако я столкнулся с проблемами с дженериками. Я не могу расширить Range<Int>, поэтому мне пришлось попытаться расширить Range.

Ближайшим я получил это, но он не работает, поскольку >= и <= не определены для ForwardIndex

extension Range {
    func contains(val:ForwardIndex) -> Bool {
        return val >= self.startIndex && val <= self.endIndex
    }
}

Как мне добавить метод .contains в Range? Или есть лучший способ определить, попадает ли значение в диапазон?

Edit2: Это, похоже, работает для расширения Range

extension Range {
    func contains(val:T) -> Bool {
        for x in self {
            if(x == val) {
                return true
            }
        }

        return false
    }
}

var a = 0..5
a.contains(3) // true
a.contains(6) // false
a.contains(-5) // false

Меня очень интересует оператор ~ =, упомянутый ниже; глядя на это сейчас.

4b9b3361

Ответ 1

Вы можете сделать это с помощью оператора ~=:

let point = (1, -1)
switch point {
case let (x, y) where (0..5) ~= x:
   println("(\(x), \(y)) has an x val between 0 and 5.")
default:
   println("This point has an x val outside 0 and 5.")
}

Вы также можете сделать это непосредственно в коммутаторе:

let point = (1, -1)
let (x, y) = point
switch x {
case 0..5:
    println("yes")
default:
    println("no")
}

~= - оператор совпадения шаблонов, используемый операторами case. Подробнее см. в документах.

Ответ 2

В Swift 5, в соответствии с вашими потребностями, вы можете выбрать один из следующих вариантов, чтобы определить, содержит ли Range (или ClosedRange) значение.


1. contains(_:) метод

Range, ClosedRange, CountableRange и CountableClosedRange есть contains(_:) метод. Range contains(_:) метод имеет следующее объявление:

func contains(_ element: Bound) -> Bool

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

Использование:

let value: Int = 0
let range = -200 ..< 300
print(range.contains(value)) // prints true

2. ~=(_:_:) оператор

Range, ClosedRange, CountableRange и CountableClosedRange имеют ~=(_:_:) оператор. Оператор Range ~=(_:_:) имеет следующее объявление:

static func ~=(Range<Bound>, Bound)

Возвращает логическое значение, указывающее, включено ли значение в диапазон.

Использование:

let value = 0
let range = -200 ..< 300
print(range ~= value) // prints true

3. Смена оператора

Простой способ проверить, если Range, ClosedRange, CountableRange или CountableClosedRange содержит значение использовать переключатель выражение:

let value = 0
switch value {
case -200 ..< 300:
    print("OK") // prints "OK"
default:
    break
}

4. Сравнение с шаблоном if case

В качестве альтернативы предыдущему оператору switch вы можете использовать if case:

let value = 0
if case -200 ..< 300 = value {
    print("OK") // prints "OK"
}  

Поэтому, чтобы решить вашу проблему, вы можете использовать один из следующих вариантов:

let point = (1, -1)
switch point {
case let (x, y) where (0 ..< 5).contains(x):
    print("(\(x), \(y)) has an x val between 0 and 5.")
default:
    print("This point has an x val outside 0 and 5.")
}
let point = (1, -1)
if case let (x, y) = point, 0 ..< 5 ~= x {
    print("(\(x), \(y)) has an x val between 0 and 5.")
}

Ответ 3

Вместо того, чтобы возиться с Range, вы можете добавить простую вспомогательную функцию, подобную этой

let point = (1, -1)
switch point {
case let (x, y) where contains((0..5),x):
    println("(\(x), \(y)) has an x val between 0 and 5.")
default:
    println("This point has an x val outside 0 and 5.")
}

func contains(range :Range<Int>, x: Int)->Bool{
    for num in range{
        if(num==x){
            return true
        }
    }
    return false
}

Возможно, вы также можете сделать что-то подобное с закрытием.

Ответ 4

Если вы хотите написать расширение contains Range, используйте distanceTo для ForwardIndex, чтобы определить, попадает ли заданное значение в диапазон.

Также используйте специальный тип Element вместо общего протокола FowardIndex как тип параметра.

Оба distanceTo и Element являются частью определения Range.

extension Range {

    func contains(element: Element) -> Bool {
        return startIndex.distanceTo(element) >= 0 && element.distanceTo(endIndex) > 0
    }

}

Плюс Range уже имеет метод contains от extension SequenceType where Generator.Element : Equatable. Таким образом, вы можете просто использовать его, не набирая его самостоятельно.

Ответ 5

Я смотрел на то же самое и делал:

let r = 7...9

operator infix ~ {}
func ~ (range:Range<Int>, item:Int) -> Bool{
  return item >= range.startIndex  && item <= range.endIndex - 1
}

r ~ 9

тогда я увидел, что ~ = делает то же самое!