swiftrun-length-encoding

Any easier to read run-length Encoding in Swift?


Can anyone write run-length encoding code in swift that is easier to read than the one below or at least explains the one i got from rosettecode.org ? Here is the input& output and the code

// "WWWBWW" -> [(3, W), (1, B), (2, W)]

func encode(input: String) -> [(Int, Character)] {
    return input.characters.reduce([(Int, Character)]()) {
        if $0.last?.1 == $1 { var r = $0; r[r.count - 1].0++; return r }
        return $0 + [(1, $1)]
    }
}

Solution

  • It would be easier to understand if you use reduce(into:) instead:

    func encode(input: String) -> [(Int, Character)] {
        input.reduce(into: [(Int, Character)]()) {
            // if the second element of the last tuple of the result is equal to the current element (character) of the collection
            if $0.last?.1 == $1 {
                // increase the first element of the last tuple tuple of the result
                $0[$0.index(before: $0.endIndex)].0 += 1 
            } else {
                // otherwise add a new tuple with a value of 1 and the current element (character) to the result
                $0 += CollectionOfOne((1, $1))
            }
        }
    }
    

    encode(input: "WWWBWW")  // [(.0 3, .1 "W"), (.0 1, .1 "B"), (.0 2, .1 "W")]
    

    You can also extend Collection and implement a generic method/property

    extension Collection where Element: Equatable {
        var groupped: [(Int, Element)] {
            reduce(into: []) {
                if $0.last?.1 == $1 {
                    $0[$0.index(before: $0.endIndex)].0 += 1
                } else {
                    $0 += CollectionOfOne((1, $1))
                }
            }
        }
    }
    

    "WWWBWW".groupped    // [(.0 3, .1 "W"), (.0 1, .1 "B"), (.0 2, .1 "W")]