我正在 Swift 4.2
中编写 iOS应用来自服务器的响应是一个字符串,其值由竖线字符“ |”分隔。它包含许多行值。我想将其拆分为子数组。
响应示例:
“ 001 |苹果|红色| 002 |香蕉|黄色| 003 |葡萄|紫色”
在此示例中,输出应为包含上述水果的3个数组的数组。如果我使用response.componentsSeparatedByString("|")
,它将给我一个包含9个元素的数组,这是我不想要的。如果考虑以上示例,我需要的是一个由3个数组组成的数组,其中还包含3个元素。
预期输出:
[[001, "apple", "red"], [002, "banana", "yellow"], [003, "grapes", "purple"]]
答案 0 :(得分:4)
如果我正确地得到了您想要的结果,那么这段代码将满足您的要求:
extension Array {
func chunked(into size: Int) -> [[Element]] {
return stride(from: 0, to: self.count, by: size).map {
Array(self[$0 ..< Swift.min($0 + size, self.count)])
}
}
}
let src = "001|apple|red|002|banana|yellow|003|grapes|purple"
let result = src.split(separator: "|").map(String.init).chunked(into: 3)
// result = [["001", "apple", "red"], ["002", "banana", "yellow"], ["003", "grapes", "purple"]]
如果您知道结果子数组的预期大小,这将起作用
如果可以确定数组元素的类型为.map(String.init)
,也可以从最后一行中删除String.SubSequence
答案 1 :(得分:1)
|
字符分隔字符串let input = "001|apple|red|002|banana|yellow|003|grapes|purple"
let result: [[String]] = input
.split(separator: "|")
.reduce(into: []) { result, string in
guard let _ = Int(string) else {
result[result.count - 1].append(String(string))
return
}
result.append([])
}
/// result: [["apple", "red"], ["banana", "yellow"], ["grapes", "purple"]]
如果您也想保留001
,则将result.append([])
更改为result.append([String(string)])
:
[["001", "apple", "red"], ["002", "banana", "yellow"], ["003", "grapes", "purple"]]
此解决方案希望您的字符串以数字开头,否则会崩溃。
如果不能保证字符串以数字开头,则需要手动检查保护块中的数组是否为空。
答案 2 :(得分:1)
基本方式
let str = "001|apple|red|002|banana|yellow|003|grapes|purple"
let components = str.components(separatedBy: "|")
let chunkSize = 3
let loopCount = components.count/chunkSize
var packages: [Array<String>] = []
for index in 0..<loopCount {
/// Starting index
let numIndex = index * chunkSize
/// Get the subarray of range
let package = Array(components[numIndex..<(numIndex+chunkSize)])
packages.append(package)
}
print(packages)
输出:
[[“” 001“,”苹果“,”红色“],[” 002“,”香蕉“,”黄色“],[” 003“,”葡萄“,”紫色“]]
答案 3 :(得分:1)
借助正则表达式,借助OOPer's extension
,您可以执行类似的操作添加一个字符串扩展名,该扩展名根据正则表达式模式对字符串进行拆分。
extension String {
func split(usingRegex pattern: String) -> [String] {
//### Crashes when you pass invalid `pattern`
let regex = try! NSRegularExpression(pattern: pattern)
let matches = regex.matches(in: self, range: NSRange(0..<utf16.count))
let ranges = [startIndex..<startIndex] + matches.map{Range($0.range, in: self)!} + [endIndex..<endIndex]
return (0...matches.count).map { String(self[ranges[$0].lowerBound..<ranges[$0+1].lowerBound]) }
}
}
然后根据模式[0-9]{3}
连续3个数字分割字符串。
let str = "001|apple|red|002|banana|yellow|003|grapes|purple|004|this|is|a|test|one|005|so|is|this"
let pattern = "[0-9]{3}"
let result = str.split(usingRegex: pattern)
var all:[[String]] = []
for row in result {
let split = row.split(separator: "|").map({ (substring) in
return String(substring)
})
if split.count != 0 {
all.append(split)
}
}
dump(all)
我在操场上对此进行了测试,结果如下:
▿ 5 elements
▿ 3 elements
- "001"
- "apple"
- "red"
▿ 3 elements
- "002"
- "banana"
- "yellow"
▿ 3 elements
- "003"
- "grapes"
- "purple"
▿ 6 elements
- "004"
- "this"
- "is"
- "a"
- "test"
- "one"
▿ 4 elements
- "005"
- "so"
- "is"
- "this"
如果您决定要从结果数组中排除ID,则可以修改扩展名,返回以下内容:
return (0...matches.count).map { String(self[ranges[$0].upperBound..<ranges[$0+1].lowerBound]) }
这将切换返回范围以使用upperBound
而不是lowerBound
答案 4 :(得分:0)
好的,您可以递归进行
let input = "001|apple|red|002|banana|yellow|003|grapes|purple"
let array = input.components(separatedBy: "|")
// Get Chunks from array
extension Array {
func getFirstElements(upTo position: Int) -> Array<Element> {
let arraySlice = self[0 ..< position]
return Array(arraySlice)
}
}
func recersivelyGetArray (array:[String], slice:inout [[String]]) {
guard !array.isEmpty else{
return
}
var copyArray = array
var chunkSize = 3
if array.count >= 3 {
chunkSize = 3
} else {
chunkSize = array.count
}
let threeElements = copyArray.getFirstElements(upTo: chunkSize)
slice.append(threeElements)
copyArray.removeFirst(chunkSize)
recersivelyGetArray(array: copyArray, slice: &slice)
}
var inoutResult = [[String]]()
recersivelyGetArray(array: array, slice: &inoutResult)
print(inoutResult)
输出
案例1 用于输入
let input = "001|apple|red|002|banana|yellow|003|grapes|purple"
[[“” 001“,”苹果“,”红色“],[” 002“,”香蕉“,”黄色“],[” 003“,”葡萄“,”紫色“]]
案例2 用于输入
let input = "001|apple|red|002|banana|yellow|003|grapes"
[[“” 001“,”苹果“,”红色“],[” 002“,”香蕉“,”黄色“],[” 003“,”葡萄“]]
答案 5 :(得分:0)
您可以使用byWords选项在范围内使用String方法enumerateSubstrings,检查字符串是否为整数,如果是,则将带有该字符串的新数组追加到结果中,否则将单词追加到最后一个结果数组中:
package bounded.wildcards;
import java.util.ArrayList;
import java.util.List;
public class GenericsDemo {
public static void main(String[] args) {
// Invariance Workaround
List<Integer> numList = new ArrayList<>();
GenericsDemo.invarianceWorkaround(numList);
System.out.println(numList);
}
static <T extends Number> void invarianceWorkaround(List<T> list) {
T element = (T) new Double(23.3);
list.add(element);
}
}