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

Мало или больше, чем в инструкции переключателя Swift

Я знаком с операторами switch в Swift, но задаюсь вопросом, как заменить этот кусок кода на switch:

if someVar < 0 {
    // do something
} else if someVar == 0 {
    // do something else
} else if someVar > 0 {
    // etc
}
4b9b3361

Ответ 1

Здесь один подход. Предполагая, что someVar является Int или другим Comparable, вы можете при желании назначить операнд новой переменной. Это позволяет вам охватить его, но вы хотите использовать ключевое слово where:

var someVar = 3

switch someVar {
case let x where x < 0:
    print("x is \(x)")
case let x where x == 0:
    print("x is \(x)")
case let x where x > 0:
    print("x is \(x)")
default:
    print("this is impossible")
}

Это можно немного упростить:

switch someVar {
case _ where someVar < 0:
    print("someVar is \(someVar)")
case 0:
    print("someVar is 0")
case _ where someVar > 0:
    print("someVar is \(someVar)")
default:
    print("this is impossible")
}

Вы также можете избежать ключевого слова where с помощью соответствия диапазонов:

switch someVar {
case Int.min..<0:
    print("someVar is \(someVar)")
case 0:
    print("someVar is 0")
default:
    print("someVar is \(someVar)")
}

Ответ 2

С помощью Swift 4 вы можете выбрать один из следующих переключателей, чтобы заменить инструкцию if.


# 1 Использование переключателя с CountablePartialRangeFrom и PartialRangeUpTo

let value = 1

switch value {
case 1...:
    print("greater than zero")
case 0:
    print("zero")
case ..<0:
    print("less than zero")
default:
    fatalError()
}

# 2 Использование переключателя с CountableClosedRange, CountableRange, Int max статическим свойством и Int min статическим свойством

let value = 1

switch value {
case 1 ... Int.max:
    print("greater than zero")
case Int.min ..< 0:
    print("less than zero")
case 0:
    print("zero")
default:
    fatalError()
}

# 3 Использование переключателя с предложением where

let value = 1

switch value {
case let val where val > 0:
    print("\(val) is greater than zero")
case let val where val == 0:
    print("\(val) is zero")
case let val where val < 0:
    print("\(val) is less than zero")
default:
    fatalError()
}

# 4 Использование переключателя с предложением where и присвоением _

let value = 1

switch value {
case _ where value > 0:
    print("greater than zero")
case _ where value == 0:
    print("zero")
case _ where value < 0:
    print("less than zero")
default:
    fatalError()
}

# 5 Использование переключателя с RangeExpression протоколом ~=(_:_:) operator

let value = 1

switch true {
case 1... ~= value:
    print("greater than zero")
case ..<0 ~= value:
    print("less than zero")
default:
    print("zero")
}

# 6 Использование переключателя с Equatable протоколом ~=(_:_:) operator

let value = 1

switch true {
case value > 0:
    print("greater than zero")
case value < 0:
    print("less than zero")
case 0 ~= value:
    print("zero")
default:
    fatalError()
}

# 7 Использование переключателя с CountablePartialRangeFrom, PartialRangeUpTo и RangeExpression contains(_:) method

let value = 1

switch true {
case (1...).contains(value):
    print("greater than zero")
case (..<0).contains(value):
    print("less than zero")
default:
    print("zero")
}

Ответ 3

Оператор switch, под капотом, использует оператор ~=. Итак:

let x = 2

switch x {
case 1: print(1)
case 2: print(2)
case 3..<5: print(3..<5)
default: break
}

Desugars к этому:

if 1          ~= x { print(1) }
else if 2     ~= x { print(2) }
else if 3..<5 ~= x { print(3..<5) }
else {  }

Если вы посмотрите на стандартную ссылку на библиотеку, она может точно указать, что перегружает ~=: включено соответствие диапазонов и приравнивание для равнозначные вещи. (Не включено совпадение в виде перечисления, которое является языковой функцией, а не функцией в std lib)

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

Если... вы перегружаете оператор ~= самостоятельно. (Обычно это не рекомендуется). Одна из возможностей может быть примерно такой:

func ~= <T> (lhs: T -> Bool, rhs: T) -> Bool {
  return lhs(rhs)
}

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

func isEven(n: Int) -> Bool { return n % 2 == 0 }

switch 2 {
case isEven: print("Even!")
default:     print("Odd!")
}

В вашем случае у вас может быть инструкция, которая выглядит так:

switch someVar {
case isNegative: ...
case 0: ...
case isPositive: ...
}

Но теперь вам нужно определить новые функции isNegative и isPositive. Если вы не перегрузите еще несколько операторов...

Вы можете перегружать нормальные операторы infix, чтобы быть префиксными или постфиксными операторами. Вот пример:

postfix operator < {}

postfix func < <T : Comparable>(lhs: T)(_ rhs: T) -> Bool {
  return lhs < rhs
}

Это будет работать следующим образом:

let isGreaterThanFive = 5<

isGreaterThanFive(6) // true
isGreaterThanFive(5) // false

Объедините это с более ранней функцией, и ваш оператор switch может выглядеть так:

switch someVar {
case 0< : print("Bigger than 0")
case 0  : print("0")
default : print("Less than 0")
}

Теперь вы, вероятно, не должны использовать такие вещи на практике: это немного изворотливое. Вы, вероятно, лучше придерживаетесь утверждения where. Тем не менее, шаблон оператора switch

switch x {
case negative:
case 0:
case positive:
}

или

switch x {
case lessThan(someNumber):
case someNumber:
case greaterThan(someNumber):
}

Кажется достаточно общим, чтобы его можно было рассмотреть.

Ответ 4

Вы можете:

switch true {
case someVar < 0:
    print("less than zero")
case someVar == 0:
    print("eq 0")
default:
    print("otherwise")
}

Ответ 5

Поскольку кто-то уже отправил case let x where x < 0:, здесь есть альтернатива, где someVar - Int.

switch someVar{
case Int.min...0: // do something
case 0: // do something
default: // do something
}

И вот альтернатива, где someVar есть Double:

case -(Double.infinity)...0: // do something
// etc

Ответ 6

Вот как это выглядит с диапазонами

switch average {
    case 0..<40: //greater or equal than 0 and less than 40
        return "T"
    case 40..<55: //greater or equal than 40 and less than 55
        return "D"
    case 55..<70: //greater or equal than 55 and less than 70
        return "P"
    case 70..<80: //greater or equal than 70 and less than 80
        return "A"
    case 80..<90: //greater or equal than 80 and less than 90
        return "E"
    case 90...100: //greater or equal than 90 and less or equal than 100
        return "O"
    default:
        return "Z"
    }

Ответ 7

Выражение <0 не работает (больше?), поэтому я закончил с этим:

Swift 3.0:

switch someVar {
    case 0:
        // it zero
    case 0 ..< .greatestFiniteMagnitude:
        // it greater than zero
    default:
        // it less than zero
    }

Ответ 8

Рад, что Swift 4 решает проблему: В качестве обходного пути в 3 я сделал:

switch translation.x  {
    case  0..<200:
        print(translation.x, slideLimit)
    case  -200..<0:
        print(translation.x, slideLimit)
    default:
        break
    }

Работает, но не идеально