Swift: разбить строку на массив
Допустим, у меня есть строка:
var fullName: String = "First Last"
Я хочу разделить базу строк на пробелы и присвоить значения соответствующим переменным
var fullNameArr = // something like: fullName.explode(" ")
var firstName: String = fullNameArr[0]
var lastName: String? = fullnameArr[1]
Кроме того, иногда пользователи могут не иметь фамилии.
30 ответов:
Быстрый способ-использовать глобальную функцию
split, например:var fullName = "First Last" var fullNameArr = split(fullName) {$0 == " "} var firstName: String = fullNameArr[0] var lastName: String? = fullNameArr.count > 1 ? fullNameArr[1] : nilС Swift 2
В Swift 2 Использование split становится немного сложнее из-за введения внутреннего типа CharacterView. Это означает, что String больше не использует протоколы SequenceType или CollectionType и вместо этого необходимо использовать свойство
.charactersдля доступа к представлению типа CharacterView экземпляра String. (Примечание: CharacterView действительно принимает SequenceType и Протоколы CollectionType).let fullName = "First Last" let fullNameArr = fullName.characters.split{$0 == " "}.map(String.init) // or simply: // let fullNameArr = fullName.characters.split{" "}.map(String.init) fullNameArr[0] // First fullNameArr[1] // Last
Просто вызовите
componentsSeparatedByStringМетод на вашемfullNameimport Foundation var fullName: String = "First Last" let fullNameArr = fullName.componentsSeparatedByString(" ") var firstName: String = fullNameArr[0] var lastName: String = fullNameArr[1]Обновление для Swift 3+
import Foundation let fullName = "First Last" let fullNameArr = fullName.components(separatedBy: " ") let name = fullNameArr[0] let surname = fullNameArr[1]
Самый простой способ сделать это-использовать componentsSeparatedBy:
Для Свифта 2:
import Foundation let fullName : String = "First Last"; let fullNameArr : [String] = fullName.componentsSeparatedByString(" ") // And then to access the individual words: var firstName : String = fullNameArr[0] var lastName : String = fullNameArr[1]Для Свифта 3:
import Foundation let fullName : String = "First Last" let fullNameArr : [String] = fullName.components(separatedBy: " ") // And then to access the individual words: var firstName : String = fullNameArr[0] var lastName : String = fullNameArr[1]
Быстрый Дэв. 4.0 (май 24, 2017)
Новая функция
splitв Swift 4 ( Beta).import Foundation let sayHello = "Hello Swift 4 2017"; let result = sayHello.split(separator: " ") print(result)Вывод:
["Hello", "Swift", "4", "2017"]Доступ к значениям:
print(result[0]) // Hello print(result[1]) // Swift print(result[2]) // 4 print(result[3]) // 2017Xcode 8.1 / Swift 3.0.1
Вот способ множественных разделителей с массивом.
import Foundation let mathString: String = "12-37*2/5" let numbers = mathString.components(separatedBy: ["-", "*", "/"]) print(numbers)Вывод:
["12", "37", "2", "5"]
В качестве альтернативы ответу WMios вы также можете использовать
componentsSeparatedByCharactersInSet, что может быть удобно в случае, если у вас больше разделителей (пробел, запятая и т. д.).С вашим конкретным вводом:
let separators = NSCharacterSet(charactersInString: " ") var fullName: String = "First Last"; var words = fullName.componentsSeparatedByCharactersInSet(separators) // words contains ["First", "Last"]Использование нескольких разделителей:
let separators = NSCharacterSet(charactersInString: " ,") var fullName: String = "Last, First Middle"; var words = fullName.componentsSeparatedByCharactersInSet(separators) // words contains ["Last", "First", "Middle"]
Xcode 9 Swift 4 или Xcode 8.2.1 * Swift 3.0.2
Если вам просто нужно правильно отформатировать имя человека, вы можете использовать PersonNameComponentsFormatter.
Класс PersonNameComponentsFormatter предоставляет локализованные представления компонентов имени человека, как они представлены по объекту PersonNameComponents. Используйте этот класс для создания локализованных имена при отображении информации об имени человека в пользователь.
// iOS (9.0 and later), macOS (10.11 and later), tvOS (9.0 and later), watchOS (2.0 and later) let nameFormatter = PersonNameComponentsFormatter() let name = "Mr. Steven Paul Jobs Jr." // personNameComponents requires iOS (10.0 and later) if let nameComps = nameFormatter.personNameComponents(from: name) { nameComps.namePrefix // Mr. nameComps.givenName // Steven nameComps.middleName // Paul nameComps.familyName // Jobs nameComps.nameSuffix // Jr. // It can also be convufgured to format your names // Default (same as medium), short, long or abbreviated nameFormatter.style = .default nameFormatter.string(from: nameComps) // "Steven Jobs" nameFormatter.style = .short nameFormatter.string(from: nameComps) // "Steven" nameFormatter.style = .long nameFormatter.string(from: nameComps) // "Mr. Steven Paul Jobs jr." nameFormatter.style = .abbreviated nameFormatter.string(from: nameComps) // SJ // It can also be use to return an attributed string using annotatedString method nameFormatter.style = .long nameFormatter.annotatedString(from: nameComps) // "Mr. Steven Paul Jobs jr." }
Проблема пробелов
Как правило, люди изобретают эту проблему и плохие решения снова и снова. Это что, космос? ""а как насчет "\n", "\t" или какого-нибудь символа Юникода, который вы никогда не видели, в немалой степени потому, что он невидим. В то время как вы можете уйти сСлабое решение
import Foundation let pieces = "Mary had little lamb".componentsSeparatedByString(" ")Если вам когда-нибудь понадобится встряхнуть свою хватку в реальности, смотрите видео WWDC на строках или датах. Короче, это почти всегда лучше, чтобы позволить Apple, чтобы решить такого рода обыденная задача.
Надежное Решение: Используйте NSCharacterSet
Способ сделать это правильно, IMHO, заключается в использовании
NSCharacterSet, так как, как говорилось ранее, ваш пробел может быть не тем, что вы ожидаете, и Apple предоставила набор символов пробела. Чтобы изучить различные наборы символов, ознакомьтесь с документацией разработчика Nscharacterset от Apple , а затем, только после этого, дополните или создайте новый набор символов, если он не соответствует вашим потребностям.NSCharacterSet пробелы
Возвращает набор символов, содержащий символы в Unicode General Категория Zs и таблица символов (U+0009).
let longerString: String = "This is a test of the character set splitting system" let components = longerString.components(separatedBy: .whitespaces) print(components)
Swift 4 значительно упрощает разделение символов, просто используйте новую функцию разделения для строк.
Пример:
let s = "hi, hello" let a = s.split(separator: ",") print(a)Теперь у вас есть массив с "привет" и "привет".
Swift 3
let line = "AAA BBB\t CCC" let fields = line.components(separatedBy: .whitespaces).filter {!$0.isEmpty}
- возвращает три строки
AAA,BBBиCCC- отфильтровывает пустые поля
- обрабатывает несколько пробелов и символов табуляции
- Если вы хотите обрабатывать новые строки, то замените
.whitespacesна.whitespacesAndNewlines
Xcode 8.0 / Swift 3
let fullName = "First Last" var fullNameArr = fullName.components(separatedBy: " ") var firstname = fullNameArr[0] // First var lastname = fullNameArr[1] // LastДолгий Путь:
var fullName: String = "First Last" fullName += " " // this will help to see the last word var newElement = "" //Empty String var fullNameArr = [String]() //Empty Array for Character in fullName.characters { if Character == " " { fullNameArr.append(newElement) newElement = "" } else { newElement += "\(Character)" } } var firsName = fullNameArr[0] // First var lastName = fullNameArr[1] // Last
Я нашел интересный случай, что
Метод 1
var data:[String] = split( featureData ) { $0 == "\u{003B}" }Когда я использовал эту команду для разделения некоторого символа из данных, загруженных с сервера , он может разделяться во время тестирования в симуляторе и синхронизации с тестовым устройством, но он не будет разделяться в приложении публикации и Ad Hoc
Мне потребуется много времени, чтобы отследить эту ошибку, она может быть проклята из какой-то версии Swift, или какой-то версии iOS, или ни того ни другого
Это также не касается HTML-кода, так как я пытаюсь stringByRemovingPercentEncoding и это все еще не работает
Дополнение 10/10/2015
В Swift 2.0 этот метод был изменен на
var data:[String] = featureData.split {$0 == "\u{003B}"}
Метод 2
var data:[String] = featureData.componentsSeparatedByString("\u{003B}")Когда я использовал эту команду, она может разделить те же данные, которые загружаются с сервера правильно
Заключение, Я действительно предлагаю использовать метод 2
string.componentsSeparatedByString("")
У меня был сценарий, в котором в строке, которую я хочу разделить, может присутствовать несколько управляющих символов. Вместо того, чтобы поддерживать массив из них, я просто позволяю Apple обрабатывать эту часть.
Следующее работает с Swift 3.0.1 на iOS 10:
let myArray = myString.components(separatedBy: .controlCharacters)
Большинство этих ответов предполагают, что входные данные содержат пробел-не Белый пробел, и при этом один пробел. Если вы можете с уверенностью сделать это предположение, то принятый ответ (от Беннетта) довольно элегантен, а также метод, который я буду использовать, когда смогу.
Когда мы не можем сделать это предположение, более надежное решение должно охватывать следующие вычисления, которые большинство ответов здесь не учитывают:
- табуляции / новые строки/пробелы (пробелы), включая повторяющиеся символы
- начальные / конечные пробелы
- Apple / Linux (
\n) и Windows (\r\n) символы новой строкиЧтобы охватить эти случаи, это решение использует регулярное выражение для преобразования всех пробелов (включая повторяющиеся и символы новой строки Windows) в один пробел, обрезает, а затем разбивает на один пробел:
Свифт 3:
let searchInput = " First \r\n \n \t\t\tMiddle Last " let searchTerms = searchInput .replacingOccurrences( of: "\\s+", with: " ", options: .regularExpression ) .trimmingCharacters(in: .whitespaces) .components(separatedBy: " ") // searchTerms == ["First", "Middle", "Last"]
Или без замыканий вы можете сделать это в Swift 2:
let fullName = "First Last" let fullNameArr = fullName.characters.split(" ") let firstName = String(fullNameArr[0])
Swift 4, Xcode 10 и iOS 12 обновляют 100% рабочий
let fullName = "First Last" let fullNameArr = fullName.components(separatedBy: " ") let firstName = fullNameArr[0] //First let lastName = fullnameArr[1] //LastСмотрите документацию компании Apple здесьдля получения дополнительной информации.
Надеюсь, что это полезно
Swift 4: разбить строку на массив. Шаг 1: назначить строку. Шаг 2: на основе @ spliting. Примечание: переменное имя.компоненты (separatedBy: "ключевое слово split")
let fullName: String = "First Last @ triggerd event of the session by session storage @ it can be divided by the event of the trigger." let fullNameArr = fullName.components(separatedBy: "@") print("split", fullNameArr)
В Swift 4.1 и Xcode 9.4.1
//This is your str let str = "This is my String" //Here replace with your stringВариант 1
let items = str.components(separatedBy: " ")//Here replase space with your value and result is Array. //Direct line of code //let items = "This is my String".components(separatedBy: " ") let str1 = items[0] let str2 = items[1] let str3 = items[2] let str4 = items[3] //OutPut print(items.count) print(str1) print(str2) print(str3) print(str4) print(items.first!) print(items.last!)Вариант 2
let items = str.split(separator: " ") let str1 = String(items.first!) let str2 = String(items.last!) //Output print(items.count) print(items) print(str1) print(str2)Вариант 3
let arr = str.split {$0 == " "} print(arr)Вариант 4
let line = "BLANCHE: I don't want realism. I want magic!" print(line.split(separator: " ")) print(line.split(separator: " ", maxSplits: 1))//This can split your string into 2 parts print(line.split(separator: " ", maxSplits: 2))//This can split your string into 3 parts print(line.split(separator: " ", omittingEmptySubsequences: false))//array contains empty strings where spaces were repeated. print(line.split(separator: " ", omittingEmptySubsequences: true))//array not contains empty strings where spaces were repeated. print(line.split(separator: " ", maxSplits: 4, omittingEmptySubsequences: false)) print(line.split(separator: " ", maxSplits: 3, omittingEmptySubsequences: true))
let str = "one two" let strSplit = str.characters.split(" ").map(String.init) // returns ["one", "two"]Xcode 7.2 (7C68)
Swift 2.2 обработка ошибок & capitalizedString добавлено:
func setFullName(fullName: String) { var fullNameComponents = fullName.componentsSeparatedByString(" ") self.fname = fullNameComponents.count > 0 ? fullNameComponents[0]: "" self.sname = fullNameComponents.count > 1 ? fullNameComponents[1]: "" self.fname = self.fname!.capitalizedString self.sname = self.sname!.capitalizedString }
Допустим, у вас есть переменная с именем "Hello World", и если вы хотите разделить ее и сохранить на две разные переменные, вы можете использовать ее следующим образом:
var fullText = "Hello World" let firstWord = fullText.text?.components(separatedBy: " ").first let lastWord = fullText.text?.components(separatedBy: " ").last
Это снова изменилось в бета-версии 5. Уиииии! Теперь это метод на CollectionType
Старый:
var fullName = "First Last" var fullNameArr = split(fullName) {$0 == " "}Новое:
var fullName = "First Last" var fullNameArr = fullName.split {$0 == " "}
Для swift 2, XCode 7.1:
let complete_string:String = "Hello world" let string_arr = complete_string.characters.split {$0 == " "}.map(String.init) let hello:String = string_arr[0] let world:String = string_arr[1]
Согласно Swift 2.2
Вы просто пишете 2-строчный код, и вы получите разделенную строку.
let fullName = "FirstName LastName" var splitedFullName = fullName.componentsSeparatedByString(" ") print(splitedFullName[0]) print(splitedFullName[1])Наслаждайтесь. :)
Вот алгоритм, который я только что построил, который разделит
Stringна любойCharacterиз массива, и если есть желание сохранить подстроки с разделенными символами, можно установить параметрswallowвtrue.Xcode 7.3-Swift 2.2:
extension String { func splitBy(characters: [Character], swallow: Bool = false) -> [String] { var substring = "" var array = [String]() var index = 0 for character in self.characters { if let lastCharacter = substring.characters.last { // swallow same characters if lastCharacter == character { substring.append(character) } else { var shouldSplit = false // check if we need to split already for splitCharacter in characters { // slit if the last character is from split characters or the current one if character == splitCharacter || lastCharacter == splitCharacter { shouldSplit = true break } } if shouldSplit { array.append(substring) substring = String(character) } else /* swallow characters that do not equal any of the split characters */ { substring.append(character) } } } else /* should be the first iteration */ { substring.append(character) } index += 1 // add last substring to the array if index == self.characters.count { array.append(substring) } } return array.filter { if swallow { return true } else { for splitCharacter in characters { if $0.characters.contains(splitCharacter) { return false } } return true } } } }Пример:
"test text".splitBy([" "]) // ["test", "text"] "test++text--".splitBy(["+", "-"], swallow: true) // ["test", "++" "text", "--"]
Обработка строк по-прежнему является сложной задачей в Swift, и она продолжает существенно меняться, как вы можете видеть из других ответов. Надеюсь, все уляжется и станет проще. Именно так можно поступить с текущей версией Swift 3.0 с несколькими разделителями символов.
Свифт 3:
let chars = CharacterSet(charactersIn: ".,; -") let split = phrase.components(separatedBy: chars) // Or if the enums do what you want, these are preferred. let chars2 = CharacterSet.alphaNumerics // .whitespaces, .punctuation, .capitalizedLetters etc let split2 = phrase.components(separatedBy: chars2)
Swift 4
let string = "loremipsum.dolorsant.amet:" let result = string.components(separatedBy: ".") print(result[0]) print(result[1]) print(result[2]) print("total: \(result.count)")Вывод
loremipsum dolorsant amet: total: 3
Я искал loozy split, такой как PHP
explode, где пустые последовательности включены в результирующий массив, это сработало для меня:"First ".split(separator: " ", maxSplits: 1, omittingEmptySubsequences: false)Вывод:
["First", ""]
Я не нашел решения, которое бы обрабатывало имена с 3 или более компонентами и поддерживало более старые версии iOS.
struct NameComponentsSplitter { static func split(fullName: String) -> (String?, String?) { guard !fullName.isEmpty else { return (nil, nil) } let components = fullName.components(separatedBy: .whitespacesAndNewlines) let lastName = components.last let firstName = components.dropLast().joined(separator: " ") return (firstName.isEmpty ? nil : firstName, lastName) } }Пройденные тестовые случаи:
func testThatItHandlesTwoComponents() { let (firstName, lastName) = NameComponentsSplitter.split(fullName: "John Smith") XCTAssertEqual(firstName, "John") XCTAssertEqual(lastName, "Smith") } func testThatItHandlesMoreThanTwoComponents() { var (firstName, lastName) = NameComponentsSplitter.split(fullName: "John Clark Smith") XCTAssertEqual(firstName, "John Clark") XCTAssertEqual(lastName, "Smith") (firstName, lastName) = NameComponentsSplitter.split(fullName: "John Clark Jr. Smith") XCTAssertEqual(firstName, "John Clark Jr.") XCTAssertEqual(lastName, "Smith") } func testThatItHandlesEmptyInput() { let (firstName, lastName) = NameComponentsSplitter.split(fullName: "") XCTAssertEqual(firstName, nil) XCTAssertEqual(lastName, nil) }
var fullName = "James Keagan Michael" let first = fullName.components(separatedBy: " ").first?.isEmpty == false ? fullName.components(separatedBy: " ").first! : "John" let last = fullName.components(separatedBy: " ").last?.isEmpty == false && fullName.components(separatedBy: " ").last != fullName.components(separatedBy: " ").first ? fullName.components(separatedBy: " ").last! : "Doe"
- запретить одинаковые имя и фамилию
- Если полное имя недопустимо, замените его значением "John Doe"

Comments