将字符串拆分为数组

时间:2019-03-28 11:12:58

标签: ios swift

我正在 Swift 4.2

中编写 iOS应用

来自服务器的响应是一个字符串,其值由竖线字符“ |”分隔。它包含许多行值。我想将其拆分为子数组。

响应示例:

  

“ 001 |苹果|红色| 002 |香蕉|黄色| 003 |葡萄|紫色”

在此示例中,输出应为包含上述水果的3个数组的数组。如果我使用response.componentsSeparatedByString("|"),它将给我一个包含9个元素的数组,这是我不想要的。如果考虑以上示例,我需要的是一个由3个数组组成的数组,其中还包含3个元素。

预期输出:

[[001, "apple", "red"], [002, "banana", "yellow"], [003, "grapes", "purple"]]

6 个答案:

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

  1. |字符分隔字符串
  2. 然后在结果数组的最后一个子数组中追加不是数字的元素
  3. 如果元素为数字,则将新的子数组添加到结果数组中
  4. 重复2-3,直到完成
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);
    }

}