Swift Algorithms Versions Save

Commonly used sequence and collection algorithms for Swift

1.2.0

5 months ago

Additions

  • Sequences have new grouped(by:) and keyed(by:) methods, which simplify building dictionaries based on sequence elements: (#197)

    let evensOdds = (1...10).grouped(by: { $0.isMultiple(of: 2) ? "even" : "odd" })
    // ["even": [2, 4, 6, 8, 10], "odd": [1, 3, 5, 7, 9]]
    
    let animals = ["Aardvark", "Alpaca", "Armadillo", "Barracuda", "Buffalo", ...]
    let alphaAnimals = animals.keyed(by: \.first!, resolvingConflictsWith: { _, first, _ in first })
    // ["A": "Aardvark", "B": "Barracuda", ...]
    
  • The endOfPrefix(while:) and startOfSuffix(while) methods are now public. These methods were previously implementation details of the trimming group of methods. (#211)

Fixes

  • Documentation and performance improvements. (#202, #210)

The 1.2.0 release includes contributions from @amomchilov, @mattyoung, @natecook1000, @stephentyrone, and @ttsugriy. Thank you!

1.1.0

6 months ago

Additions

  • New nonmutating partitioned(by:) methods that return both the failing and passing elements of a sequence or collection in separate arrays. (#152)

    let cast = ["Vivien", "Marlon", "Kim", "Karl"]
    let (longNames, shortNames) = cast.partitioned(by: { $0.count < 5 })
    
    print(longNames)
    // Prints "["Vivien", "Marlon"]"
    print(shortNames)
    // Prints "["Kim", "Karl"]"
    
  • A new evenlyChunked(in:) method that chunks a sequence or collection into the specified number of evenly-sized subsequences. (#96)

    let numbers = Array(0..<10) 
    for chunk in numbers.evenlyChunked(in: 4) {
        print(chunk)
    }
    // Prints: 
    // [0, 1, 2]
    // [3, 4, 5]
    // [6, 7]
    // [8, 9]
    

Changes

  • The package now has a minimum Swift version of Swift 5.4.

Fixes

  • Improvements to documentation, including a new DocC-based documentation structure.

The 1.1.0 release includes contributions from @dickoff, @gwynne, @mdznr, @natecook1000, @ole, @stephentyrone, and @timvermeulen. Thank you!

1.0.0

2 years ago

Swift Algorithms is now source stable!

Changes

  • Most sequence and collection types have been renamed, following a more consistent naming structure:
    • The Lazy prefix was dropped.
    • Either a Sequence or Collection suffix was added depending on whether or not the type is unconditionally a collection.
    • The base name was derived from the name of the method that produces it, including an argument label to disambiguate if necessary.
  • Types that can only be produced from a lazy sequence chain now unconditionally conform to LazySequenceProtocol and wrap the base sequence instead of the lazy wrapper, making some return types slightly simpler.
    • e.g. [1, 2, 3].lazy.reductions(+) now returns ExclusiveReductionsSequence<[Int]>, not ExclusiveReductionsSequence<LazySequence<[Int]>>.
  • The generic parameters of the ExclusiveReductions type have been swapped, putting the base collection first and the result type second.
  • The Indices associated type of IndexedCollection now matches Base.Indices.

Removals

  • Previously deprecated type and method names have been removed:
    • The Chain type alias for Chain2Sequence
    • The chained(with:) method which was replaced with the chain(_:_:) free function
    • The LazyChunked and Chunked type aliases for ChunkedByCollection
    • The rotate(subrange:at:) and rotate(at:) methods which were renamed to rotate(subrange:toStartAt:) and rotate(toStartAt:) respectively

Fixes

  • The StridingSequence and StridingCollection types now conditionally conform to LazySequenceProtocol, allowing the striding(by:) method to properly propagate laziness in a lazy sequence chain.
  • Fixed chunked(by:) to always compare two consecutive elements rather than each element with the first element of the current chunk. (#162)

0.2.1

2 years ago

Additions

Expanded versatility for two existing operations:

  • A series of joined(by:) overloads concatenate a sequence of sequences using an element or a collection, either passed in or generated from consecutive elements via a closure. (#138)
  • Additional trimming(while:) methods for trimming only the start or end of a collection, as well as mutating versions of all three variants. (#104)

0.2.0

2 years ago

Additions

Two new additions to the list of algorithms:

  • adjacentPairs() lazily iterates over tuples of adjacent elements of a sequence. (#119)
  • minAndMax() finds both the smallest and largest elements of a sequence in a single pass. (#90)

Changes

  • When calling chunked(on:), the resulting collection has an element type of (Subject, SubSequence) instead of just SubSequence, making the subject value available when iterating.

    let numbers = [5, 6, -3, -9, -11, 2, 7, 6]
    for (signum, values) in numbers.chunked(on: { $0.signum() }) {
        print(signum, values)
    }
    // 1 [5, 6]
    // -1 [-3, -9, -11]
    // 1 [2, 7, 6]
    

Fixes

  • Improvements to the documentation and PR templates.

0.1.1

3 years ago

Fixes

  • Product2 associated type inference error in release build (#130)

0.1.0

3 years ago

Additions

  • The compacted() method lazily finds the non-nil elements of a sequence or collection (#112).

Changes

  • The uniqued() method now lazily computes the unique elements of a sequence or a collection (#71). Pass this resulting sequence to an Array initializer to recover the behavior of the previous release.
  • Calling cycled(times:) now returns a new FiniteCycle type, which has the same conformances as its underlying collection (#106).
  • The base collections of the sequence and collection wrapper types are no longer public (#85, #125), and the wrapper types no longer conform to the Equatable or Hashable protocols (#124). If you need those conformances, convert the wrapper type to an Array or other collection currrency type before storing. Please file an issue if these changes pose a problem for your use case.

0.0.4

3 years ago

Additions

More new algorithms to join the party:

  • A lazy version of the standard library's two split methods. (#78)
  • firstNonNil(_:) returns the first non-nil element from an optional-generating transform. (#31)
  • uniquePermutations() skips duplicates when generating permutations of a collection. (#91)
  • The reductions methods return all the in-between states of reducing a sequence or collection. (#46)

Fixes

  • Methods and computed properties are more consistently marked as inlinable, resolving a performance regression.
  • The Stride type now efficiently calculates distances between positions, supported by the underlying collection.
  • Better test coverage and improved diagnostics for comparing sequences.
  • Fixed links and improved documentation.

0.0.3

3 years ago

Additions

An exciting group of new algorithms, contributed by the community:

  • trimming(while:) returns a subsequence of a bidirectional collection with the matching elements removed from the start and end. (#4)
  • min(ofCount:) and max(ofCount:) find the smallest or largest elements in a collection. (#9, #77)
  • windows(ofCount:) lets you iterate over all the overlapping subsequences of a particular length. (#20)
  • striding(by:) iterates over every nth element of a sequence or collection. (#24)
  • interspersed(with:) places a new element between every pair of elements in a sequence or collection. (#35)
  • chunks(ofCount:) breaks a collection into subsequences of the given number of elements. (#54)
  • suffix(while:) matches the standard library's prefix(while:), by returning the suffix of all matching elements from a bidirectional collection. (#65)
  • Variations of combinations(ofCount:) and permutations(ofCount:) that take a range expression as a parameter, returning combinations and permutations of multiple lengths. (#51, #56)

Changes

  • The LazyChunked type now precomputes its startIndex, making performance more predictable when using the collection.

Fixes

  • randomSample(count:) no longer traps in rare circumstances.
  • Index calculations have been improved in a variety of collection wrappers.
  • A variety of documentation improvements and corrections.

0.0.2

3 years ago

Changes

  • The rotate(at:) method has been updated to rotate(toStartAt:), with the old name deprecated.
  • The chained(with:) method has been changed to the free function chain(_:_:), with the old version deprecated.
  • Algorithms now uses RealModule from the swift-numerics package for its cross-platform elementary functions.
  • Sequence/collection wrapper types, like Permutations and Indexed, now have conformance to the lazy protocols, so that any following operations maintain their laziness.

Fixes

  • Swift Algorithms now builds under SwiftPM on Windows.
  • A wide variety of errors, misspellings, and ommissions in the documentation and guides have been fixed.
  • Index/distance calculations for the Product2 and Chain types have been corrected.
  • Calling stablePartition(subrange:by:) now correctly uses the subrange's length instead of the whole collection.