Last active
November 8, 2019 00:39
-
-
Save a-voronov/9d96abc5696115c98a868de50f4ef9b1 to your computer and use it in GitHub Desktop.
Lightweight Data-Structure for Storing One or More Elements π
This file contains 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
public indirect enum OneOrMore<T> { | |
case one(T) | |
case more(T, Self) | |
} | |
// MARK: Creation simplified | |
public extension OneOrMore { | |
static func few(_ head: T, _ tail: T...) -> OneOrMore { | |
few(head, tail) | |
} | |
static func few<S>(_ head: T, _ tail: S) -> OneOrMore where S: Sequence, S.Element == T { | |
var many: OneOrMore = .one(head) | |
for value in tail { | |
many = .more(value, many) | |
} | |
return many | |
} | |
} | |
// MARK: Adding elements | |
public extension OneOrMore { | |
mutating func add(_ other: T) { | |
self = adding(other) | |
} | |
func adding(_ other: T) -> Self { | |
.more(other, self) | |
} | |
} | |
// MARK: Array representation | |
public extension OneOrMore { | |
var array: [T] { | |
switch self { | |
case let .one(value): | |
return [value] | |
case let .more(value, other): | |
var copy = other.array | |
copy.append(value) | |
return copy | |
} | |
} | |
} | |
// MARK: Set representation | |
public extension OneOrMore where T: Hashable { | |
var set: Set<T> { | |
switch self { | |
case let .one(value): | |
return [value] | |
case let .more(value, other): | |
var copy = other.set | |
copy.insert(value) | |
return copy | |
} | |
} | |
} | |
// MARK: Equatable & Hashable | |
extension OneOrMore: Equatable where T: Equatable {} | |
extension OneOrMore: Hashable where T: Hashable {} | |
// MARK: Debugging | |
extension OneOrMore: CustomDebugStringConvertible { | |
public var debugDescription: String { | |
array.debugDescription | |
} | |
} | |
// MARK: Decompose collection to map into OneOrMore | |
extension Collection { | |
func decompose() -> (head: Element, tail: [Element])? { | |
first.map { head in | |
(head: head, tail: Array(dropFirst())) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example
Note
Not intended for big data-sets, as it takes N steps to compose into user-friendly representation.
However fits good for something small like errors or validations sets, etc.