Разбить строку на массив в Swift?


688

Скажем, у меня есть строка здесь:

var fullName: String = "First Last"

Я хочу разбить строку базы на пустое пространство и присвоить значения их соответствующим переменным

var fullNameArr = // something like: fullName.explode(" ") 

var firstName: String = fullNameArr[0]
var lastName: String? = fullnameArr[1]

Кроме того, иногда пользователи могут не иметь фамилию.


13
Привет, у меня нет моего Mac, чтобы проверить. Но вы можете попробовать 'fullName.componentsSeparatedByString (string: "")' Не копировать и вставлять, используйте функцию автозаполнения, чтобы получить правильную функцию.
Дэвид Гольжойзер

Если вы только расщепление на один символ, с помощью fullName.utf8.split( <utf-8 character code> )произведений , а также (заменить .utf8с .utf16на UTF-16). Например, разделение +может быть сделано с помощьюfullName.utf8.split(43)
Jojodmo

Кроме того, иногда в фамилиях есть пробелы, как в «Дафни дю Мурье» или «Шарль де Линт»
Берри

Ответы:


784

Способ Swift заключается в использовании глобальной 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 

98
В моих тестах componentSeparatedByString обычно значительно быстрее, особенно при работе со строками, которые требуют разбиения на множество частей. Но для примера, указанного в OP, должно хватить любого.
Кейси Перкинс

9
Начиная с Xcode 6.2b3 разделение может использоваться как split("a:b::c:", {$0 == ":"}, maxSplit: Int.max, allowEmptySlices: false).
Паскаль

14
Просто помните, что вам все еще нужно использовать старый componentsSeparatedByString()метод, если ваш разделитель длиннее одного символа. И, как ни крути, это, к let (firstName, lastName) = split(fullName) {$0 == ' '}сожалению, не работает.
NRitH

3
@Kashif, тогда вы можете использовать split("a,b;c,d") {$0 == "," || $0 == ";"}илиsplit("a,b;c,d") {contains(",;", $0)}
Итан

4
Правильный код для Xcode 7.0: let fullNameArr = fullName.characters.split {$ 0 == ""} .map (String.init). Пытался редактировать, но он был отклонен.
skagedal

1017

Просто вызовите componentsSeparatedByStringметод на вашемfullName

import 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]

3
Обратите внимание, что это на самом деле базовый NSString(Swift автоматически меняет их при импорте Foundation).
Может

1
Что больше не имеет место в Swift 1.2, в которой Apple больше не преобразует Swift String в NSString автоматически.
Elcuco

6
Этот ответ работает в Xcode 7 beta 4 и Swift 2.0. Xcode теперь автоматически завершает методы Foundation для объектов Swift String без приведения типов к NSString, что не имеет место в Xcode 6.4 с Swift 1.2.
Андрей

1
Это не работало в REPL, пока я не импортировал Фонд.
Велизар Христов

1
Это работает точно так, как ожидалось (то есть fullNameArr [String]) в Xcode 7.2.
Джон Кокс

185

Самый простой способ сделать это - использовать componentsSeparatedBy:

Для Swift 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]

Для Swift 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]

Это где-нибудь задокументировано, Мори? Что если мне нужно разделить что-то, кроме одного символа?
NRitH

10
@NRitH рассмотреть .componentsSeparatedByCharactersInSet(.whitespaceAndNewlineCharacterSet())
rmp251

@Crashalot есть две функции: componentsSeparatedByStringиcomponentsSeparatedByCharactersInSet
rmp251

132

Swift Dev. 4.0 (24 мая 2017 г.)

Новая функция splitв Swift 4 ( бета ).

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]) // 2017

Xcode 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"]

8
Обязательно добавьте import Foundationв класс, в котором вы это используете. #SavedYouFiveMinutes
Адриан

4
Внимание (Swift 4): если у вас есть строка, подобная let a="a,,b,c"и используемая, a.split(separator: ",")вы получаете массив, подобный ["a", "b", c"]по умолчанию. Это можно изменить, используя значение omittingEmptySubsequences: falsetrue по умолчанию.
OderWat

2
Какие-нибудь многосимвольные сплиты в Swift 4+?
Пкамб

57

Swift 4 или позже

Если вам просто нужно правильно отформатировать имя человека, вы можете использовать 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 configured 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."
}

введите описание изображения здесь

редактировать / обновление:

Swift 5 или позже

Для простого разбиения строки не буквенными символами мы можем использовать новое свойство Character isLetter:

let fullName = "First Last"

let components = fullName.split{ !$0.isLetter }
print(components)  // "["First", "Last"]\n"

1
@DarrellRoot, вам просто нужно отобразить подстрокиfullName.split { $0.isWhitespace }.map(String.init)
Лев Дабус

2
Мне нравится этот новый API, но имейте в виду, что он возвращает подстроки. Мне нужны были строки (и я хотел разделить пробелы в общем), поэтому я сделал это: let words = line.split{ $0.isWhitespace }.map{ String($0)} Спасибо @LeoDabus за вашу версию (в моем исходном комментарии отсутствовал код). Также я предлагаю перенести версию Swift 5 в начало ответа.
Даррелл Рут

53

В качестве альтернативы ответу 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"]

2
Наиболее полезный ответ, на мой взгляд, поскольку вы можете разрешить разделение строк с помощью ,или ;или любым другим разделителем
Крис


34

Проблема пробелов

Как правило, люди заново изобретают эту проблему и плохие решения снова и снова. Это пространство? "", а как насчет "\ n", "\ t" или какого-либо другого символа Юникода, который вы никогда не видели, в немалой степени, потому что он невидим. В то время как вы можете сойти с рук

Слабое решение

import Foundation
let pieces = "Mary had little lamb".componentsSeparatedByString(" ")

Если вам когда-нибудь понадобится расстаться с реальностью, посмотрите видео WWDC о строках или датах. Короче говоря, почти всегда лучше позволить Apple решить эту обычную задачу.

Надежное решение: используйте NSCharacterSet

Способ сделать это правильно, IMHO, заключается в использовании, NSCharacterSetпоскольку, как указывалось ранее, ваш пробел может не соответствовать вашим ожиданиям, и Apple предоставила набор пробелов. Чтобы изучить различные предоставляемые наборы символов, ознакомьтесь с документацией разработчика NSCharacterSet от Apple, а затем, только тогда, дополните или создайте новый набор символов, если он не соответствует вашим потребностям.

NSCharacterSet пробелы

Возвращает набор символов, содержащий символы в Unicode General Category Zs и CHARACTER TABULATION (U + 0009).

let longerString: String = "This is a test of the character set splitting system"
let components = longerString.components(separatedBy: .whitespaces)
print(components)

2
Согласовано. Первое, что пришло мне в голову после просмотра ответов, разделенных на "", это: что произойдет, если входной текст содержит несколько последовательных пробелов? Что делать, если у него есть вкладки? Полноширинное (CJK) пространство? и т. д.
Николас Миари

31

В Swift 4.2 и Xcode 10

//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 the result is Array.
//Direct single 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: " "))
// Prints "["BLANCHE:", "I", "don\'t", "want", "realism.", "I", "want", "magic!"]"

По документации Apple ...

let line = "BLANCHE:   I don't want realism. I want magic!"
print(line.split(separator: " "))
// Prints "["BLANCHE:", "I", "don\'t", "want", "realism.", "I", "want", "magic!"]"

print(line.split(separator: " ", maxSplits: 1))//This can split your string into 2 parts
// Prints "["BLANCHE:", "  I don\'t want realism. I want magic!"]"

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.
// Prints "["BLANCHE:", "", "", "I", "don\'t", "want", "realism.", "I", "want", "magic!"]"

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))

23

Swift 4 значительно облегчает разделение символов, просто используйте новую функцию разделения для строк.

Пример: let s = "hi, hello" let a = s.split(separator: ",") print(a)

Теперь у вас есть массив с "привет" и "привет".


Обратите внимание, что это не возвращает массив String, но массив Substring, который неудобно использовать.
Лирик

19

Обновление для Swift 5 и самый простой способ

let paragraph = "Bob hit a ball, the hit BALL flew far after it was hit. Hello! Hie, How r u?"

let words = paragraph.components(separatedBy: [",", " ", "!",".","?"])

Это печатает,

["Боб", "удар", "a", "мяч", "", ",", "удар", "ШАР", "полетел", "далеко", "после", "это", "был "," hit "," "," Hello "," ", Hie", "", "How", "r", "u", ""]]

Однако, если вы хотите отфильтровать пустую строку,

let words = paragraph.components(separatedBy: [",", " ", "!",".","?"]).filter({!$0.isEmpty})

Вывод,

["Боб", "удар", "a", "мяч", "the", "удар", "BALL", "полетел", "далеко", "после", "это", "было", " хит "," Привет "," Hie "," Как "," R "," U "]

Но убедитесь, что фонд импортируется


17

Свифт 3

let line = "AAA    BBB\t CCC"
let fields = line.components(separatedBy: .whitespaces).filter {!$0.isEmpty}
  • Возвращает три строки AAA, BBBиCCC
  • Отфильтровывает пустые поля
  • Обрабатывает несколько пробелов и символов табуляции
  • Если вы хотите обрабатывать новые строки, то замените .whitespacesна.whitespacesAndNewlines

15

Обновление 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 здесь для получения дополнительной информации.


13

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

9

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

Следующее работает с Swift 3.0.1 на iOS 10:

let myArray = myString.components(separatedBy: .controlCharacters)

8

Интересный случай я обнаружил, что

способ 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("")

1
Я бы сказал, что это близко к статусу «не ответ», так как в основном это комментарий к существующим ответам. Но это указывает на что-то важное.
Рикстер

8

Большинство из этих ответов предполагает , что ввод содержит пробел - не белое пространство и единое пространство в этом. Если вы можете с уверенностью сделать это предположение, то принятый ответ (от Беннетта) довольно элегантный, а также метод, который я буду использовать, когда смогу.

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

  • табуляция / переводы строк / пробелы (пробелы), включая повторяющиеся символы
  • ведущий / конечный пробел
  • Символы новой строки в 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"]

6

Или без замыканий вы можете сделать это в Swift 2:

let fullName = "First Last"
let fullNameArr = fullName.characters.split(" ")
let firstName = String(fullNameArr[0])

6

Шаги по разбиению строки на массив в Swift 4.

  1. назначить строку
  2. на основе @ расщепления.

Примечание: variableName.components (separaBy: "ключевое слово 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)

4

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

3

Допустим, у вас есть переменная с именем «Hello World», и если вы хотите разделить ее и сохранить в двух разных переменных, вы можете использовать так:

var fullText = "Hello World"
let firstWord = fullText.text?.components(separatedBy: " ").first
let lastWord = fullText.text?.components(separatedBy: " ").last

3

Это дает массив разделенных частей напрямую

var fullNameArr = fullName.components(separatedBy:" ")

тогда вы можете использовать как это,

var firstName: String = fullNameArr[0]
var lastName: String? = fullnameArr[1]

3

Только splitправильный ответ, здесь разница для более чем 2 пробелов.

var temp = "Hello world     ni hao"
let arr  = temp.components(separatedBy: .whitespacesAndNewlines)
// ["Hello", "world", "", "", "", "", "ni", "hao"]
let arr2 = temp.components(separatedBy: " ")
// ["Hello", "world", "", "", "", "", "ni", "hao"]
let arr3 = temp.split(whereSeparator: {$0 == " "})
// ["Hello", "world", "ni", "hao"]


2

Swift 2.2 Обработка ошибок и добавленная заглавная строка:

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
}

2

Обработка строк все еще остается проблемой в Swift, и она постоянно меняется, как вы можете видеть из других ответов. Надеюсь, все успокоится, и это станет проще. Это способ сделать это с текущей версией 3.0 Swift с несколькими символами-разделителями.

Свифт 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)

2

Я искал слабое разбиение, такое как PHP, explodeгде пустые последовательности включены в результирующий массив, это работало для меня:

"First ".split(separator: " ", maxSplits: 1, omittingEmptySubsequences: false)

Вывод:

["First", ""]


1

Для 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]

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", "--"]
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.