Fix removeEmpty()

This commit is contained in:
ryohey
2021-07-14 21:46:03 +09:00
parent 161a9d04d3
commit d29eada4bb
2 changed files with 69 additions and 35 deletions
+32 -27
View File
@@ -1,33 +1,38 @@
import Foundation
private protocol EmptyRemovable {
func removeEmpty() -> Self
var isEmpty: Bool { get }
}
extension Array: EmptyRemovable {
public func removeEmpty() -> Array {
return compactMap {
if let e = ($0 as? EmptyRemovable)?.removeEmpty() {
return e.isEmpty ? nil : e as? Element
}
return $0
private func convertEmptyToNil<T>(_ value: T) -> T? {
switch value as Any {
case Optional<Any>.none:
return nil
case let arr as Array<Any>:
let arr = arr.removeEmpty()
if !arr.isEmpty,
let arr = arr as? T {
return arr
} else {
return nil
}
}
}
extension Dictionary: EmptyRemovable {
// this is a little trick that defines the generics parameter from optional Value to unwrapped Value
private static func removeEmpty<Key, Value>(dict: Dictionary<Key, Value?>) -> Dictionary<Key, Value> {
return dict.compactMapValues {
if let e = ($0 as? EmptyRemovable)?.removeEmpty() {
return e.isEmpty ? nil : e as? Value
}
return $0
case let dict as Dictionary<AnyHashable, Any>:
let dict = dict.removeEmpty()
if !dict.isEmpty,
let dict = dict as? T {
return dict
} else {
return nil
}
}
public func removeEmpty() -> Dictionary<Key, Value> {
return Dictionary.removeEmpty(dict: self)
default:
return value
}
}
extension Array {
public func removeEmpty() -> Self {
compactMap(convertEmptyToNil)
}
}
extension Dictionary {
public func removeEmpty() -> Self {
compactMapValues(convertEmptyToNil)
}
}
@@ -86,14 +86,43 @@ class SpecGeneratorTests: XCTestCase {
}
func testRemoveEmpty() {
let arr = [[], [1, [2], []], [3]]
let removed = arr.removeEmpty()
XCTAssertEqual(removed.count, 2)
describe {
$0.it("removes empty arrays from array") {
let arr = [[], [1], [], [2, 3]]
XCTAssertEqual(arr.removeEmpty(), [[1], [2, 3]])
}
let dict: [String: Any?] = ["e": nil]
let removed2: [String: Any?] = dict.removeEmpty()
XCTAssertEqual(removed2.count, 0)
let removed3: [String: Any] = dict.compactMapValues { $0 }
XCTAssertEqual(removed3.count, 0)
$0.it("removes nils from array") {
let arr = [nil, 1, nil, 2, 3]
XCTAssertEqual(arr.removeEmpty(), [1, 2, 3])
}
$0.it("removes nils and empty arrays from array") {
let arr = [nil, [1], nil, [2], []]
XCTAssertEqual(arr.removeEmpty(), [[1], [2]])
}
$0.it("removes nils and empty arrays from nested array") {
let arr: [[[Int?]?]] = [[[1, nil], nil, []]]
XCTAssertEqual(arr.removeEmpty(), [[[1]]])
}
$0.it("removes empty dictionaries from array") {
let dict = [["foo": 1], [:], ["bar": 2]]
XCTAssertEqual(dict.removeEmpty(), [["foo": 1], ["bar": 2]])
}
$0.it("removes nils from dictionary") {
let dict = ["foo": nil, "bar": 1]
let b = dict.removeEmpty()
XCTAssertEqual(b, ["bar": 1])
}
$0.it("removes empty dictionaries from dictionary") {
let dict = ["foo": [:], "bar": ["x": 1]]
let b = dict.removeEmpty()
XCTAssertEqual(b, ["bar": ["x": 1]])
}
}
}
}