2017-02-19 19 views
1

Я играю с приложением, которое принимает пользовательский ввод и печатает простой вывод.Неверно-чувствительный оператор switch быстро?

Мой код выглядит следующим образом:

switch text { 
     case "Hi", "hi", "Hello", "hello", "Good day", "good day": 
      return "Hello, sir." 
     default: 
      return "Sorry, I didn't understand!" 
} 

Мой вопрос, вместо того, чтобы иметь 5-10 возможных входов на один выход, можно поставить один вход, который не чувствителен к регистру? Например, могу ли я просто поместить «привет» и проверить мой оператор на «Hello», «hello», «HELLO» и т. Д.?

+4

'switch text.lowercased()' и введите строки с нижним регистром только в разных случаях вашего оператора 'switch'. Просто обратите внимание, что некоторые специальные символы не переводятся, как можно было бы ожидать при применении 'lowercased()' или 'uppercased()' к ним: см. [Следующие вопросы и ответы для деталей] (http://stackoverflow.com/questions/30532728/how-to-compare-two-strings-ignoring-case-in-swift-language) (в частности, комментарии к вопросу). – dfri

ответ

4

Вы можете прописные text (или в нижнем регистре [lowercased()], как указано в комментариях), так что дело не имеет значения:

switch text.uppercased() { 
case "HI", "HELLO", "GOOD DAY": 
    return "Hello, sir." 
default: 
    return "Sorry, I didn't understand!" 
} 
+0

спасибо! Я об этом не думал! –

2

Альтернативное решение:

func check(input: String) -> Bool { 
    let strings = ["Hi", "hi", "Hello", "hello", "Good day", "good day"] 

    let inputLowercase = input.lowercased() 
    return strings.first(where: { $0.lowercased() == inputLowercase }) != nil 
} 
+2

Обратите внимание, что всякий раз, когда вы используете инструкцию типа '... first (где: ...)! = Nil', например. ищет некоторый элемент, заданный некоторым предикатом, но не используя этот элемент_, вы можете просто использовать 'contains (where: ...)' вместо этого. Например, выше, 'return strings.contains (где: {$ 0.lowercased() == input.lowercased()})'. Однако, поскольку вы не применяете сопоставление с образцом, нет оснований не использовать уже имеющиеся инструменты без учета регистра, которые уже доступны (здесь, из 'Foundation'): например. 'return strings.contains (где: {$ 0.caseInsensitiveCompare (input) == .orderedSame})'. – dfri

3

Самое элегантное решение следует использовать меньшее количество String.CompareOptions в сочетании с .range(of:, options:). Это позволяет выполнять много сложных операций с меньшими усилиями, например , что позволяет игнорировать специальные символы, а не только случай и использование регулярного выражения (что было бы большим преимуществом для вашей конкретной цели). Если вы не знаете, что это такое, я рекомендую вам изучить его.

Обращайтесь на сайт: Вы можете узнать больше о String.CompareOptionshere. Документация предназначена для NSString, но они также доступны для String.

Вы бы затем использовать его следующим образом:

let userInput = "HeLLö, how are you doing? Greetings!" 

let acceptedWords = ["hello", "hi", "greeting"] 

var resultCommants = acceptedWords.filter { (word) -> Bool in 
    return userInput.range(of: word, options: [.caseInsensitive, .diacriticInsensitive]) != nil 
} 

// resultCommands = ["hello", "greeting"] 

Как вы можете видеть, HeLLö матчи hello и Greetings матчи greeting из-за .caseInsensitive и .diacriticInsensitive.

Если вы не знакомы с оператором .filter, он выполняет итерацию через ваш массив и для каждого элемента word ожидает, что вы вернете либо true, либо false, в зависимости от того, должен ли элемент быть включен в отфильтрованную версию вашего массив. Здесь это делается путем сравнения результата .range(of:, options:) с nil. Unequal nil означает, что слово было найдено, равное nil, если нет. Для детальной конкретной информации о , там, где было установлено, что данное слово найдено.

+0

Этот подход хорош, если мы хотим объединить несколько вариантов сравнения, но я считаю, используя ['compare (_: options:)'] (https://developer.apple.com/reference/foundation/nsstring/1410893-compare) и тестирование vs. '.orderedSame' имеет лучшую семантику (в этом контексте), чем' range (...) 'test vs non-'nil' (поскольку в этом контексте мы фактически не используем диапазон, произвольно полученный по вызову 'range (of: options:)'). – dfri

+0

Да, ты прав. В конечном итоге это сводится к тому же. Для меня важно использовать 'options', особенно' .diacriticInsensitive', что в противном случае было бы чрезвычайно сложно реализовать ('.caseInsensitive' намного проще). –

+0

Хотелось бы, чтобы они реализовали 'contains (_: options:)' для использования опций сравнения в более простой, более чистой функции Bool. –