Skip to content

DandyLyons/KindaSortaEqual

Repository files navigation

KindaSortaEqual

Tools for checking whether two values are "close" to equal in Swift.

This package offers small, focused APIs for a few common "near equality" paradigms:

  • Unordered collection equality (compare collections ignoring order)
  • Value proximity checks via AlmostEquatable.
  • Selective equality via SelectiveEquatable (check only specific key paths)
  • "equivalence" checking (experimental).

Overview

Many comparisons don't require strict, bit-for-bit equality. This package provides helpers to express common "close enough" equality checks in a clear, testable way.

Key concepts

  • hasSameElements(as:) — compare two collections for equality while ignoring element order.
  • AlmostEquatable — a protocol for types that can be compared within a threshold (tolerance).
  • SelectiveEquatable — a protocol (from the SelectiveEquatable package) where equality is performed only on the provided key paths.
  • equivalence (experimental): SelectiveEquatable package vends a set of isEquivalent(to:). These compare two collections, ignore order, and verify that each collection has exactly one element with a matching id and other values.

Installation

Add the package to your Package.swift dependencies:

.package(url: "https://github.com/yourusername/KindaSortaEqual.git", from: "0.1.0"),

Then add the product to your target dependencies.

Usage

Below are short examples for the main paradigms. They assume the helpers are exported from the KindaSortaEqual module.

Unordered collection equality

Use hasSameElements(as:) to check two collections contain the same elements regardless of order. This is useful when element order is not meaningful.

import KindaSortaEqual

let a = [1, 2, 3]
let b = [3, 1, 2]
let c = [1, 2, 3, 3]

a.hasSameElements(as: b) // true
a.hasSameElements(as: c) // false

To count as true, both collections must contain the same elements with the same multiplicity. The order of elements does not matter.

AlmostEquatable protocol

AlmostEquatable is a lightweight protocol used to express that two values are "close" by some measure (for example, within a tolerance for floating point values). Types conforming to AlmostEquatable implement a method such as isAlmostEqual(to:threshold:).

import KindaSortaEqual

extension Double: AlmostEquatable {
    func isAlmostEqual(to other: Double, threshold: Double = 1e-8) -> Bool {
        return abs(self - other) <= threshold
    }
}

let x: Double = 0.30000000000000004
let y: Double = 0.3
print(x.isAlmostEqual(to: y, threshold: 1e-12))

The package includes conformances and helpers for arrays, floating point types, CoreGraphics types, and some common custom types—see the Sources/KindaSortaEqual/AlmostEquatable folder for concrete implementations and tests.

The library comes with several built-in conformances for common types including:

  • Double, Float
  • CGPoint, CGSize, CGRect
  • Date
  • Array
  • UIColor, NSColor

SelectiveEquatable protocol

SelectiveEquatable (from the SelectiveEquatable package) lets you state equality in terms of a set of key paths. Provide the key paths you care about and equality will be checked only for those properties.

Refer to the Sources/KindaSortaEqual/SelectiveEquatable.swift for the exact API surface used by this package.

Conforming to SelectiveEquatable is as simple as:

extension MyType: SelectiveEquatable {}

That's it. No methods need to be implemented. If you have any equatable properties then you can instantly benefit from SelectiveEquatable.

let person1 = Person(name: "Alice", age: 30, address: "123 Main St")
let person2 = Person(name: "Alice", age: 30, address: "456 Elm St")
person1.isEqual(to: person2, by: \.name, \.age) // true

Other Approaches

Be sure to check out Uncertain by Mattt which has some similar ideas but is solving a fundamentally different problem.

Contributing

Contributions are welcome. Please open issues or PRs. Keep changes small and focused. Add tests for new behavior.

License

Licensed by the MIT License. This repository includes a LICENSE file—please refer to it for licensing information.

About

Swift convenience APIs for values that are kind of, sort of equal.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages