Skip to content

Instantly share code, notes, and snippets.

@jnozzi
Created May 1, 2019 14:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jnozzi/e19fe497e374801f08a8a8fc346e40ea to your computer and use it in GitHub Desktop.
Save jnozzi/e19fe497e374801f08a8a8fc346e40ea to your computer and use it in GitHub Desktop.
Handy utility for turning a collection of strings into a characterwise matrix for comparison within columns and retrieval of substrings from column ranges. Handles simple Range<Int> <---> Range<String.Index> conversions.
//
// Created by Joshua Nozzi on 4/29/19.
// Copyright © 2019 Joshua Nozzi. All rights reserved.
//
import Foundation
struct StringMatrix {
var rows: Int { return strings.count }
var columns: Int { return strings.map{ $0.count }.max() ?? 0 }
init(_ strings: [String]) { self.strings = strings }
func substringsAtColumn(_ column: Int) -> [Substring?] {
return (0..<rows).map { self[$0, column] }
}
func substringsWithColumnRange(_ columnRange: Range<Int>) -> [Substring?] {
assert(columnRangeIsValid(columnRange), "Out of column range")
return (0..<rows).map {
let string = strings[ $0 ]
guard let stringRange = safeColumnRangeIn(columnRange, inString: string) else { return nil }
return string[ stringRange ]
}
}
subscript(row: Int, column: Int) -> Substring? {
get {
assert(indexIsValid(row: row, column: column), "Index out of range")
let string = strings[row]
guard column < string.count else { return nil }
guard let range = Range(NSRange(location: column, length: 1), in: string) else { return nil }
return string[range]
}
}
// MARK: Private
private let strings: [String]
private func indexIsValid(row: Int, column: Int) -> Bool {
return row >= 0 && row < rows && column >= 0 && column < columns
}
private func columnRangeIsValid(_ columnRange: Range<Int>) -> Bool {
return columnRange.lowerBound >= 0 && columnRange.upperBound <= columns
}
private func safeColumnRangeIn(_ columnRange: Range<Int>, inString string: String) -> Range<String.Index>? {
return Range(NSRange(columnRange.clamped(to: 0..<string.count)), in: string)
}
}
// MARK: - Helper Extensions
extension Collection where Element == String {
var matrix: StringMatrix { return StringMatrix(self as! [String]) }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment