How to transpose an array of strings

前端 未结 3 528
伪装坚强ぢ
伪装坚强ぢ 2020-12-20 20:23

I\'ve a txt including some data in the following format.

AYGA:GKA:GOROKA:GOROKA:PAPUA NEW GUINEA:06:04:54:S:145:23:30:E:5282
AYLA:LAE::LAE:PAPUA NEW GUINEA:0         


        
相关标签:
3条回答
  • 2020-12-20 20:56

    Perhaps more generically (and with a zip like behaviour):

    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
        }
    }
    

    Now we can use it like so:

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

    ... which returns:

    [[0, 10, 100], [1, 11, 101], [2, 12, 102], [3, 13, 103], [4, 14, 104]]
    
    0 讨论(0)
  • 2020-12-20 21:12

    What you are trying to do is called a transposition. Turning an array that looks like:

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

    into an array that looks like:

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

    To do this, let's define a generic function for transposition and apply it to your problem

    // 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)
    

    You can see the results of the transposition with

    for result in results {
        print("\(result)")
    }
    

    Which generates (for your example)

    ["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"]
    

    This has the advantage of not depending on the number of arrays that you have, and the number of subarrays is taken from the count of the first array.

    You can download an example playground for this, which has the input as a file in the playground's resources.

    0 讨论(0)
  • 2020-12-20 21:14

    Here is another alternative that handles different newline characters well and doesn't require any hard coding to get the correct number of arrays. The number of colon-separated components is read from the first line.

    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)
        }
    }
    
    0 讨论(0)
提交回复
热议问题