Как разбить строку по новым строкам в Swift

Это поведение, когда приложение появляется из полноэкранного режима при переключении сцен, является странным (это происходит и для меня на Java 8u60, OS X 10.11.3). Это может быть ошибка .

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

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class FullScreenScenes extends Application {
    @Override
    public void start(Stage stage) throws Exception {
        Button next1 = new Button("Show Scene 2");
        StackPane layout1 = new StackPane(next1);
        layout1.setStyle("-fx-background-color: palegreen;");

        Button next2 = new Button("Show Scene 1");
        StackPane layout2 = new StackPane(next2);
        layout2.setStyle("-fx-background-color: paleturquoise;");

        Scene scene = new Scene(layout1);

        next1.setOnAction(event -> scene.setRoot(layout2));
        next2.setOnAction(event -> scene.setRoot(layout1));

        stage.setScene(scene);
        stage.setFullScreen(true);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

29
задан Community 23 May 2017 в 12:34
поделиться

8 ответов

в Xcode 8.2, Swift 3.0.1:

Использовать метод метода NSString компонентов (separaBy:)

let text = "line1\nline2"
let array = text.components(separatedBy: CharacterSet.newlines)

Или использовать String Метод enumerateLines , как и ответ Leo Dabus

18
ответ дан zagger 23 May 2017 в 12:34
поделиться

Swift 5 или более поздняя версия

Вы можете разделить String, используя новое свойство Character isNewline :

let sentence = "Line 1\nLine 2\nLine 3\n"
var lines = sentence.split { [110].isNewline }
print(lines)   // "[Line 1, Line 2, Line 3]"
< hr>

Оригинальный ответ

Вы можете использовать метод String enumerateLines :

Перечисляет все строки в строке.

Swift 3 или новее

let sentence = "Line 1\nLine 2\nLine 3\n"
var lines: [String] = []
sentence.enumerateLines { line, _ in
    lines.append(line)
}
print(lines)   // "[Line 1, Line 2, Line 3]"
<час>
extension String {
    var lines: [String] {
        var result: [String] = []
        enumerateLines { line, _ in result.append(line) }
        return result
    }
}
<час>

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

let sentence2 = "Line 4\nLine 5\nLine 6\n"
let sentence2Lines = sentence2.lines

print(sentence2Lines)    // ["Line 4", "Line 5", "Line 6"]


let sentence3 = "Line 7\r\nLine 8\r\nLine 9\r\n"
let sentence3Lines = sentence3.lines

print(sentence3Lines)  // "[Line 7, Line 8, Line 9]"
47
ответ дан Leo Dabus 23 May 2017 в 12:34
поделиться

В Swift 2 функция split верхнего уровня теперь является методом в CollectionType (которому соответствует каждое из «114 представлений символов» String). Есть две версии метода, вы хотите, чтобы тот, который принимает замыкание в качестве предиката, указывает, должен ли данный элемент рассматриваться как разделитель.

Вы можете получить набор символов из строки в виде набора символов UTF16, используя string.utf16, что делает их совместимыми с API NSCharacterSet. Таким образом, мы можем легко проверить внутри замыкания, является ли данный символ в строке членом набора символов новой строки.

Стоит отметить, что split(_:) вернет SubSequence символов (в основном, Slice), поэтому его необходимо преобразовать обратно в массив строк, что, как правило, более полезно. Я сделал это ниже, используя flatMap(String.init) - инициализатор UTF16View в String не работает, поэтому использование flatMap будет игнорировать любые значения nil, которые могут быть возвращены, гарантируя, что вы получите массив необязательных строк назад.

Итак, для хорошего Swift-подобного способа сделать это:

let str = "Line 1\nLine 2\r\nLine 3\n"
let newlineChars = NSCharacterSet.newlineCharacterSet()
let lines = str.utf16.split { newlineChars.characterIsMember([110]) }.flatMap(String.init)
// lines = ["Line 1", "Line 2", "Line 3"]

Что делает это приятным, так это то, что метод split имеет параметр allowEmptySubsequences, который гарантирует, что вы не получите никакого пустые последовательности символов в результате. По умолчанию это false, так что вам вообще не нужно его указывать.

Редактировать

Если вы хотите вообще избежать NSCharacterSet, вы можете так же легко разделить коллекцию юникод-совместимых Character сек.

let lines = str.characters.split { [111] == "\n" || [111] == "\r\n" }.map(String.init)

Свифт может рассматривать "\r\n" как один расширенный кластер графем, используя его как один Character для сравнения вместо создания String. Также обратите внимание, что инициализатор для создания строки из Character не является неисправным, поэтому мы можем просто использовать map.

9
ответ дан Stuart 23 May 2017 в 12:34
поделиться

Для справки, Фонд Свифта CharacterSet может использоваться в пределах разделения:

альтернатива 1

extension String {
    var lines: [String] {
        return split { String([110]).rangeOfCharacter(from: .newlines) != nil }.map(String.init)
    }
}

альтернатива 2

extension String {
    var lines: [String] {
        return split { CharacterSet.newlines.contains([111].unicodeScalars.first!) }.map(String.init)
    }
}
3
ответ дан Cœur 23 May 2017 в 12:34
поделиться
let test1 = "Line1\n\rLine2\nLine3\rLine4"
let t1 = test1.componentsSeparatedByCharactersInSet(NSCharacterSet.newlineCharacterSet())
let t2 = t1.filter{ [110] != "" }
let t3 = t1.filter{ ![110].isEmpty }
6
ответ дан user3441734 23 May 2017 в 12:34
поделиться

Swift 4:

Я бы рекомендовал сначала сохранить CSV в строку, если вы этого еще не сделали, а затем «очистить» строку, удалив ненужные возвраты каретки

        let dataString = String(data: yourData!, encoding: .utf8)!

        var cleanFile = dataString.replacingOccurrences(of: "\r", with: "\n")
        cleanFile = cleanFile.replacingOccurrences(of: "\n\n", with: "\n")

Выше вы получите строку с наиболее желательным форматом, затем вы можете отделить строку, используя \ n в качестве разделителя:

        let csvStrings = cleanFile.components(separatedBy: ["\n"])

Теперь у вас есть массив из 3 элементов, таких как :

["Line1", "Line2", "Line3"]

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

["Line1, Line2, Line3", "LineA, LineB, LineC"]

        let component0 = csvStrings[0].components(separatedBy: [","]) // ["Line1","Line2","Line3"]
        let component1 = csvStrings[1].components(separatedBy: [","]) // ["LineA","LineB","LineC"]
0
ответ дан Alan Gonzalez 23 May 2017 в 12:34
поделиться

Как разделить строку при любом разрыве строки, чтобы получить массив String без каких-либо пустых элементов?

Вы были почти там - это просто замыкающее замыкание, которое здесь другое:

let array = stringFromFile.componentsSeparatedByCharactersInSet(NSCharacterSet.newlineCharacterSet()).filter{![110].isEmpty}

То же самое, что:

let newLineChars = NSCharacterSet.newlineCharacterSet() // newline characters defined as (U+000A–U+000D, U+0085)
let array = stringFromFile.componentsSeparatedByCharactersInSet(newLineChars).filter{![111].isEmpty}

ETA: убраны лишние лишние скобки при замыкающем замыкании

1
ответ дан simons 23 May 2017 в 12:34
поделиться

Этот ответ является кратким изложением других решений, уже предоставленных. Это происходит из моего более полного ответа , но было бы полезно иметь фактические варианты выбора доступных здесь.

Новые строки обычно создаются с символом \n, но также могут быть сделаны с \r\n (из файлов, сохраненных в Windows).

Решения

1. componentsSeparatedByCharactersInSet

let multiLineString = "Line 1\nLine 2\r\nLine 3\n"
let newlineChars = NSCharacterSet.newlineCharacterSet()
let lineArray = multiLineString.componentsSeparatedByCharactersInSet(newlineChars).filter{![110].isEmpty}
// "[Line 1, Line 2, Line 3]"

Если бы filter не использовалось, то \r\n выдает пустой элемент массива, потому что он считается как два символа и поэтому разделяет строку дважды в одном месте .

[Тысяча сто тридцать одна] [1 137] 2. split

let multiLineString = "Line 1\nLine 2\r\nLine 3\n"
let newlineChars = NSCharacterSet.newlineCharacterSet()
let lineArray = multiLineString.utf16.split { newlineChars.characterIsMember([111]) }.flatMap(String.init)
// "[Line 1, Line 2, Line 3]"

или

let multiLineString = "Line 1\nLine 2\r\nLine 3\n"
let lineArray = multiLineString.characters.split { [112] == "\n" || [112] == "\r\n" }.map(String.init)
// "[Line 1, Line 2, Line 3]"

Здесь \r\n учитывается как один символ Swift (расширенный кластер графем)

3. enumerateLines

let multiLineString = "Line 1\nLine 2\r\nLine 3\n"
var lineArray = [String]()
multiLineString.enumerateLines { (line, stop) -> () in
    lineArray.append(line)
}
// "[Line 1, Line 2, Line 3]"

Подробнее о синтаксисе enumerateLine см. Также в этот ответ .

Примечания:

  • многострочная строка обычно не смешивает \r\n и \n, но я делаю это здесь, чтобы показать, что эти методы могут обрабатывать оба формата.
  • NSCharacterSet.newlineCharacterSet() - символы новой строки, определенные как (U + 000A – U + 000D, U + 0085), которые включают в себя \r и \n.
  • Этот ответ является кратким изложением ответов на мой предыдущий вопрос . Прочитайте эти ответы для более подробной информации.
  • [+1139]
6
ответ дан Community 23 May 2017 в 12:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: