如何转置字符串数组

时间:2015-10-03 07:21:38

标签: string swift

我有一个包含以下格式的数据的文本。

AYGA:GKA:GOROKA:GOROKA:PAPUA NEW GUINEA:06:04:54:S:145:23:30:E:5282
AYLA:LAE::LAE:PAPUA NEW GUINEA:00:00:00:U:00:00:00:U:0000
AYMD:MAG:MADANG:MADANG:PAPUA NEW GUINEA:05:12:25:S:145:47:19:E:0020

如何分隔用冒号(“:”)区分的每个项目以及如何将每个部分加载到数组中,如下例所示?

var array1 = ["AYGA", "AYLA", "AYMD"]
var array2 = ["GKA", "LAE", "MAG"]
var array3 = ["GOROKA", "", "MADANG"]
var array4 = ["GOROKA", "LAE", "MADANG"]
var array5 = ["PAPUA NEW GUINEA", "PAPUA NEW GUINEA", "PAPUA NEW GUINEA"]
var array6 = ["06", "00", "05"]
var array7 = ["04", "00", "12"]
var array8 = ["54", "00", "25"]
var array9 = ["S", "U", "S"]
var array10 = ["145", "00", "145"]
var array11 = ["23", "00", "47"]
var array12 = ["30", "00", "19"]
var array13 = ["E", "U", "E"]
var array14 = ["5282", "0000", "0020"]

3 个答案:

答案 0 :(得分:8)

您要做的事情称为转置。转动一个看起来像的数组:

[[1, 2, 3], [4, 5, 6]]

进入一个看起来像这样的数组:

[[1, 4], [2, 5], [3, 6]]

要做到这一点,让我们定义一个用于转置的通用函数并将其应用于您的问题

// Import the text file from the bundle

guard
    let inputURL = NSBundle.mainBundle().URLForResource("input", withExtension: "txt"),
    let input = try? String(contentsOfURL: inputURL)
    else { fatalError("Unable to get data") }

// Convert the input string into [[String]]
let strings = input.componentsSeparatedByString("\n").map { (string) -> [String] in
    string.componentsSeparatedByString(":")
}

// Define a generic transpose function.
// This is the key to the solution.

public func transpose<T>(input: [[T]]) -> [[T]] {
    if input.isEmpty { return [[T]]() }
    let count = input[0].count
    var out = [[T]](count: count, repeatedValue: [T]())
    for outer in input {
        for (index, inner) in outer.enumerate() {
            out[index].append(inner)
        }
    }

    return out
}

// Transpose the strings
let results = transpose(strings)

您可以使用

查看转置的结果
for result in results {
    print("\(result)")
}

生成(为您的示例)

["AYGA", "AYLA", "AYMD"]
["GKA", "LAE", "MAG"]
["GOROKA", "", "MADANG"]
["GOROKA", "LAE", "MADANG"]
["PAPUA NEW GUINEA", "PAPUA NEW GUINEA", "PAPUA NEW GUINEA"]
["06", "00", "05"]
["04", "00", "12"]
["54", "00", "25"]
["S", "U", "S"]
["145", "00", "145"]
["23", "00", "47"]
["30", "00", "19"]
["E", "U", "E"]
["5282", "0000", "0020"]

这样做的好处是不依赖于你拥有的数组的数量,并且从第一个数组的计数中获取子数组的数量。

您可以download an example playground为此,其中输入作为操场资源中的文件。

答案 1 :(得分:1)

这是另一种替代方案,可以很好地处理不同的换行符,并且不需要任何硬编码来获得正确数量的数组。从第一行读取冒号分隔的组件数。

let input = "AYGA:GKA:GOROKA:GOROKA:PAPUA NEW GUINEA:06:04:54:S:145:23:30:E:5282\nAYLA:LAE::LAE:PAPUA NEW GUINEA:00:00:00:U:00:00:00:U:0000\nAYMD:MAG:MADANG:MADANG:PAPUA NEW GUINEA:05:12:25:S:145:47:19:E:0020"
var arrays: [[String]]?
input.enumerateLines { (line, _) in
    let chunks = line.componentsSeparatedByString(":")

    if arrays == nil {
        arrays = [[String]](count: chunks.count, repeatedValue: [String]())
    }

    chunks.enumerate().forEach { item in
        arrays?[item.index].append(item.element)
    }
}

答案 2 :(得分:0)

也许更通用(并且具有类似行为的zip):

extension Sequence where
    Element: Collection,
    Element.Index == Int,
    Element.IndexDistance == Int
{
    public func transposed(prefixWithMaxLength max: Int = .max) -> [[Element.Element]] {
        var o: [[Element.Element]] = []
        let n = Swift.min(max, self.min{ $0.count < $1.count }?.count ?? 0)
        o.reserveCapacity(n)
        for i in 0 ..< n {
            o.append(map{ $0[i] })
        }
        return o
    }
}

现在我们可以像这样使用它:

[0..<5, 10..<20, 100..<200]
    .map(Array.init)
    .transposed()

...返回:

[[0, 10, 100], [1, 11, 101], [2, 12, 102], [3, 13, 103], [4, 14, 104]]