Как я могу разделить многострочный строковый литерал с необязательными переменными в Swift

Я пытаюсь получить индекс элемента, содержащегося в определенном классе, который соответствует глобальной переменной. Поиск узлов с помощью запросов CSS дает мне список с потенциальными совпадающими элементами, но — как документация Канны указывает, что такие запросы возвращают XPathObjects, которые действуют как массивы. Единственный способ, которым я вижу, чтобы получить значения индекса из указанного списка, - это преобразовать его из массива в строку, которую затем можно разделить на новые строки; однако я не могу заставить список принимать строковое значение. Соответствующая часть типичного журнала сеанса компиляции выглядит следующим образом:

Kazuo®/Ishiguro® Auprès® (2 pack)
Orange
Kazuo®/Ishiguro® Auprès® Folio Toujours (2 Pack)
Blue
…

Я пробовал три метода, предложенных одним плакатом в этот поток, чтобы объединить вывод выше:

1). компонентыSeparatedByCharactersInSet

for node in (doc?.css("a[class^='product-link']"))! {
    let multiLineString = node.text!
    let newlineChars = NSCharacterSet.newlineCharacterSet()
    let lineArray = multiLineString.componentsSeparatedByCharactersInSet(newlineChars).filter{!  $0.isEmpty}
}   

В идеале это напечатает [Kazuo®/Ishiguro® Auprès® (2 pack), Orange, Kazuo®/Ishiguro® Auprès® Folio Toujours (2 Pack), Blue]; вместо этого выдает ошибку. Нажатие fix приводит к еще одной ошибке — и еще одной.

2). расколоть

for node in (doc?.css("a[class^='product-link']"))! { 
    let multiLineString = node.text!
    let newlineChars = NSCharacterSet.newlineCharacterSet()
    let lineArray = multiLineString.utf16.split { newlineChars.characterIsMember($0) }.flatMap(String.init)
}

Дает тот же результат, что и componentsSeparatedByCharactersInSet: Cannot call value of non-function type 'CharacterSet' -> fix -> ошибка -> fix -> ошибка.

3). enumerateLines

for node in (doc?.css("a[class^='product-link']"))! {             
    let multiLineString = node.text!
    var lineArray = [String]()
    multiLineString.enumerateLines { (line, stop) -> () in
        lineArray.append(line)
    }
}

Это решение фактически создает, но возвращает каждый элемент списка как function().

Эти методы работают, когда я пробую их с простыми многострочными строковыми литералами в Playgrounds, но по какой-то причине они не работают с выводом выше. Самый простой способ решить эту проблему — использовать func index(of element: Element) -> Int?, но это дает мне ошибку Cannot convert value of type 'String' to expected argument type 'Character'. Я новичок в Swift, поэтому, если кто-нибудь с большим опытом может предложить альтернативные подходы к этой проблеме, я был бы очень признателен за помощь!


person solo    schedule 01.01.2018    source источник


Ответы (3)


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

var prodIndex = 0
var testProd = "Prod" // to be replaced by user input

for node in (doc?.css("a[class^='name-link']"))! {
    let words = testProd.split(separator: " ")
    if prodIndex % 2 == 0 {
        if node.text! == testProd {
            print("FOUND: " + testProd)
        }

        prodIndex += 1
    }
}
person ch1maera    schedule 07.01.2018

Код устарел. Первый метод в Swift 3+ —

let newlineChars = CharacterSet.newlines
let lineArray = multiLineString.components(separatedBy: newlineChars).filter{ !$0.isEmpty }

Чтобы поместить текст в одну строку, используйте

let oneLine = multiLineString.components(separatedBy: newlineChars).filter{ !$0.isEmpty }.joined(separator: " ")
person vadian    schedule 01.01.2018
comment
Это дает мне: ["Kazuo®/Ishiguro® Auprès® (2 pack)"]\n["Orange"]\n["Kazuo®/Ishiguro® Auprès® Folio Toujours (2 Pack)"]\n["Blue"]. Как я могу получить их на одной линии? Разделение по новой строке просто повторяет проблемы, продемонстрированные выше. - person solo; 01.01.2018

Я думаю, ты пытаешься сказать, что хочешь

Kazuo®/Ishiguro® Auprès® (2 pack)
Orange
Kazuo®/Ishiguro® Auprès® Folio Toujours (2 Pack)
Blue

как однострочная строка правильная?

for node in (doc?.css("a[class^='product-link']"))! {
    // suggestion: use a guard here, it's good practice to safely unwrap optionals
    guard let multiLineString = node.text else { return }

    let lineArray = multiLineString.components(separatedBy: .newlines).joined(separator: " ")
 }

отпечатки: Kazuo®/Ishiguro® Auprès® (2 pack) Orange Kazuo®/Ishiguro® Auprès® Folio Toujours (2 Pack) Blue

person mmr118    schedule 01.01.2018
comment
Хм, по какой-то причине я все еще получаю исходный вывод Kazuo®/Ishiguro® Auprès® (2 pack)\nOrange\nKazuo®/Ishiguro® Auprès® Folio Toujours (2 Pack)\nBlue. Может ли это быть системной проблемой? - person solo; 01.01.2018
comment
Попробуйте переключить .newlines на ”\n” - person mmr118; 01.01.2018
comment
Хм, может быть, в вопросе чего-то не хватает, что неочевидно, потому что мне ничего не ясно, почему это должно было сработать. - person mmr118; 01.01.2018
comment
Как вы справляетесь с lineArray после его назначения? - person mmr118; 01.01.2018
comment
Когда я запускаю print(lineArray), он дает мне тот же результат, что и выше. - person solo; 01.01.2018
comment
На самом деле меня очень беспокоит, что это не работает. Если хотите, мой твиттер указан в аккаунте, если хотите, можете отправить мне прямое сообщение, и мы можем попробовать более подробно подойти к этому вопросу. - person mmr118; 02.01.2018