'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 1:[1]
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")]
Solution 2:[2]
Hope this make it easier for you to understand.
func encode2(input: String) -> [(Int, Character)] {
var result = [(Int, Character)]()
input.forEach { char in
if result.last?.1 == char {
result[result.count - 1].0 += 1
} else {
result.append((1, char))
}
}
return result
}
Solution 3:[3]
I've solved the task with the following way, which may be more clear for someone:
func compress(input: String) -> [(Int, Character)] {
var output = [(Int, Character)]()
var count: Int = 1 // count of repeated characters
var i = 0
while i < input.count { // select the current character
var j = i + 1
while j < input.count &&
input[input.index(input.startIndex, offsetBy: i)] == input[input.index(input.startIndex, offsetBy: j)] { // count repeated charactes followed the current one
count += 1
j += 1
}
output.append((count, input[input.index(input.startIndex, offsetBy: i)]))
i = j // move index for the current character to the index of the last repeated one
count = 1 // reset count
}
return output
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Leo Dabus |
Solution 2 | congnd |
Solution 3 | Yulia |