Created
May 1, 2019 14:04
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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