Как проверить, начинается ли строка с буквы алфавита в Swift 5?

Проблема: в настоящее время я пытаюсь Sort a List in SwiftUI в соответствии с Items First Character. Я также хотел бы реализовать Section для всех предметов, которые doesn't begin с Character of the Alphabet (числа, специальные символы).

Мой код до сих пор:

let nonAlphabetItems = items.filter { $0.name.uppercased() != /* beginns with A - Z */ }

У кого-нибудь есть решение этой проблемы. Конечно, я мог бы сделать огромную Loop Construct, но я надеюсь, что есть более элегантный способ.

Спасибо за вашу помощь.

Буква включает нестандартные буквы или только "A"..."Z"? Следует ли считать букву "Ç"?

Leo Dabus 18.12.2020 17:36

@LeoDabus Только стандартные буквы от «A» до «Z». Специальные буквы, такие как «Ç», а также цифры и специальные символы должны проходить фильтрацию.

christophriepe 18.12.2020 17:37

@LeoDabus «Ç» — это стандартная буква: она соответствует стандарту Unicode, и стандарт распознает ее как букву. Есть также много стандартных букв в греческом или кириллице. Я полагаю, что под «нестандартным» вы имеете в виду «не римский»? ;-)

Christophe 01.01.2022 19:59

@ Кристоф, поэтому я и спросил. Ç — это буква, но ее нет в английском алфавите

Leo Dabus 01.01.2022 21:50

@LeoDabus Извините, без обид. Я даже проголосовал за ваш интересный ответ. Я дразню вас терминологией. «Стандартный алфавит» — это не «английский алфавит», за исключением 379 миллионов носителей английского языка среди 7,9 миллиардов людей в мире. Так что у 96% населения мира другое понимание "стандартного алфавита" ;-) Кстати, английский алфавит - это даже не английский, это латинский/латинский ;-)

Christophe 01.01.2022 22:47
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
5
2 514
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

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


let phrase = "Test case"
let range = phrase.rangeOfCharacter(from: characterSet)

// range will be nil if no letters is found
if let test = range {
    println("letters found")
}
else {
   println("letters not found")
}```

ОП пытается проверить первый символ только "начинается с"

Leo Dabus 18.12.2020 17:38

Вы можете проверить, содержит ли диапазон строк "A"..."Z" первую букву вашего имени:

struct Item {
    let name: String
}

let items: [Item] = [.init(name: "Def"),.init(name: "Ghi"),.init(name: "123"),.init(name: "Abc")]

let nonAlphabetItems = items.filter { !("A"..."Z" ~= ($0.name.first?.uppercased() ?? "#")) }

nonAlphabetItems  // [{name "123"}]

Развивая эту тему, мы можем расширить Character, чтобы добавить свойство isAsciiLetter:

extension Character {
    var isAsciiLetter: Bool { "A"..."Z" ~= self || "a"..."z" ~= self }
}

Это позволит расширить StringProtocol, чтобы проверить, начинается ли строка с буквы ascii:

extension StringProtocol {
    var startsWithAsciiLetter: Bool { first?.isAsciiLetter == true }
}

И просто помощник для отрицания логического свойства:

extension Bool {
    var negated: Bool { !self }
}

Теперь мы можем отфильтровать коллекцию элементов следующим образом:

let nonAlphabetItems = items.filter(\.name.startsWithAsciiLetter.negated)   // [{name "123"}]

Спасибо за Ваш ответ. Что такое оператор ~=?

christophriepe 18.12.2020 17:41

В этом случае это то же самое, что и содержит. Это называется оператором сопоставления с образцом. Это также можно записать как {!("A"..."Z").contains(($0.name.first?.uppercased() ?? "#")) }

Leo Dabus 18.12.2020 17:42

Вы можете иметь дело со значением ascii

extension String {
    var fisrtCharacterIsAlphabet: Bool {
         guard let firstChar = self.first else { return false }
         let unicode = String(firstChar).unicodeScalars
         let ascii = Int(unicode[unicode.startIndex].value)
         return (ascii >= 65 && ascii <= 90) || (ascii >= 97 && ascii <= 122)
    }
    
}

var isAlphabet = "Hello".fisrtCharacterIsAlphabet

Тип Character имеет для этого свойство:

let x: Character = "x"
x.isLetter // true for letters, false for punctuation, numbers, whitespace, ...

Обратите внимание, что это будет включать символы из других алфавитов (греческий, кириллический, китайский, ...).

Поскольку String — это Sequence, где Element равно Character, мы можем использовать свойство .first, чтобы получить первый символ.

При этом вы можете фильтровать свои товары:

let filtered = items.filter { $0.name.first?.isLetter ?? false }
isLetter также будет включать нежелательные буквы. Вот почему я разместил комментарий, спрашивая об этом в первую очередь. developer.apple.com/documentation/swift/character/…
Leo Dabus 18.12.2020 18:30

Вы можете сделать это с помощью этого простого расширения String

extension StringProtocol {
    var isFirstCharacterAlp: Bool {
        first?.isASCII == true && first?.isLetter == true
    }
}

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

print ("H1".isFirstCharacterAlp)
print ("ابراهيم1".isFirstCharacterAlp)

Выход

true
false

Удачного кодирования!

Ссылка

Почему бы просто свойство Character не isLetter, как предложил Палле? Кстати, это не решит вопрос, потому что он также будет включать буквы, отличные от ascii.

Leo Dabus 18.12.2020 18:34

@LeoDabus Я обновил свой ответ. Спасибо за указание на ограничение ASCII. Я пропустил комментарии.

Md. Ibrahim Hassan 18.12.2020 18:44

ИМО self.first?.isASCII == true читается намного лучше, чем self.first?.isASCII ?? false. Кстати скобки не нужны first?.isASCII == true && first?.isLetter == true

Leo Dabus 18.12.2020 18:46

@LeoDabus Да, удаление скобок выглядит чище, согласился и обновил блок кода.

Md. Ibrahim Hassan 18.12.2020 18:51

Я бы просто удалил префикс self и расширил StringProtocol вместо поддержки подстрок.

Leo Dabus 18.12.2020 18:52

Согласен Спасибо за предложения.

Md. Ibrahim Hassan 18.12.2020 18:54
Ответ принят как подходящий

Если вам нужен случайный фильтр, вы можете просто написать условие, объединяющее стандартные предикаты isLetter и isASCII, которые уже определены для Character. Это так же просто, как:

let items = [ "Abc", "01bc", "Ça va", "", "  ", "𓀫𓀫𓀫𓀫"]
let nonAlphabetItems = items.filter { $0.isEmpty || !$0.first!.isASCII || !$0.first!.isLetter }
print (nonAlphabetItems)  // -> Output:  ["01bc", "Ça va", "", "  ", "𓀫𓀫𓀫𓀫"]

Если строка не пуста, в ней наверняка есть первый символ $0.first!. Заманчиво использовать isLetter , но это верно для многих символов во многих местных алфавитах, включая, например, античные египетские иероглифы , такие как "𓀫", или французский алфавит с "Ç" и акцентированными символами. Вот почему вам нужно ограничить его буквами ASCII, чтобы ограничить себя латинским алфавитом.

Не нужно принудительно разворачивать $0.isEmpty || $0.first?.isASCII == false || $0.first?.isLetter == false

Leo Dabus 02.01.2022 22:27

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