Как транспонировать массив строк
У меня есть текст, включая некоторые данные в следующем формате.
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 ответа
То, что вы пытаетесь сделать, называется транспозицией. Превращение массива, который выглядит как:
[[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"]
Преимущество этого состоит в том, что вы не зависите от количества имеющихся у вас массивов, а количество подмассивов берется из числа первых массивов.
Вы можете загрузить пример игровой площадки для этого, который имеет входные данные в виде файла в ресурсах игровой площадки.
Вот еще одна альтернатива, которая хорошо обрабатывает различные символы новой строки и не требует жесткого кодирования для получения правильного числа массивов. Количество компонентов, разделенных двоеточиями, читается из первой строки.
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)
}
}
Возможно, в более общем смысле (и с 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]]