I'm trying to get the index of an element contained in a certain class that matches a global variable. Searching for nodes with CSS queries gives me a list with potential matching elements, but — as Kanna's documentation points out — such queries return XPathObjects
that act as arrays. The only way I can see to get index values from said list is to convert it from an array into a string, which can then be split by new lines; however, I can't seem to get the list to take a string value. The relevant part of a typical compile session log follows:
Kazuo®/Ishiguro® Auprès® (2 pack)
Orange
Kazuo®/Ishiguro® Auprès® Folio Toujours (2 Pack)
Blue
…
I've tried three methods suggested by one poster in this thread to concatenate the above output:
1). componentsSeparatedByCharactersInSet
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}
}
Ideally, this would print [Kazuo®/Ishiguro® Auprès® (2 pack), Orange, Kazuo®/Ishiguro® Auprès® Folio Toujours (2 Pack), Blue]
; it raises an error instead. Clicking fix
leads to another error — and another one.
2). split
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)
}
Yields the same result as componentsSeparatedByCharactersInSet
: Cannot call value of non-function type 'CharacterSet'
-> fix
-> error -> fix
-> error.
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)
}
}
This solution actually builds, but it returns each list item as function()
.
These methods work when I try them on simple multi-line string literals in Playgrounds, but for some reason they don't work on the output above. The easiest way to solve this problem would be to use func index(of element: Element) -> Int?
, but doing so gives me a Cannot convert value of type 'String' to expected argument type 'Character'
error. I'm new to Swift, so if anyone with more experience could suggest alternative approaches to this problem, I would much appreciate the help!
Regarding your larger goal, this is how you should go about solving the problem:
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
}
}
The code is outdated. The first method in Swift 3+ is
let newlineChars = CharacterSet.newlines
let lineArray = multiLineString.components(separatedBy: newlineChars).filter{ !$0.isEmpty }
To put the text in one line use
let oneLine = multiLineString.components(separatedBy: newlineChars).filter{ !$0.isEmpty }.joined(separator: " ")
I think you are trying to say you want
Kazuo®/Ishiguro® Auprès® (2 pack)
Orange
Kazuo®/Ishiguro® Auprès® Folio Toujours (2 Pack)
Blue
as a single line string correct?
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: " ")
}
prints: Kazuo®/Ishiguro® Auprès® (2 pack) Orange Kazuo®/Ishiguro® Auprès® Folio Toujours (2 Pack) Blue
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.