Git Product home page Git Product logo

sortedarray's Introduction

SortedArray

A sorted array type for Swift 4.0+.

Provides the SortedArray type, an array that keeps its elements sorted according to a given sort predicate.

Written by Ole Begemann, February 2017.

For more info, see the GitHub repo and my accompanying blog article.

Supported Platforms

The current release supports Swift 4.0 and up.

If you need support for older Swift version, here's a list of the latest releases that support specific Swift versions:

Swift version Latest SortedArray release
4.x master
3.x 0.6.0
3.0 0.4

Since the code has no dependencies other than the Swift standard library (it doesn't even use Foundation), it should work on all platforms where Swift is available.

I tested it on macOS, iOS, tvOS, and Linux.

Usage

Swift Package Manager

Add this to your Package.swift file:

// Package.swift
import PackageDescription

let package = Package(
    name: "<Your package name>",
    dependencies: [
        .Package(url: "https://github.com/ole/SortedArray.git", majorVersion: 0)
    ]
)

Carthage

Add this to your Cartfile:

github "ole/SortedArray" ~> 0.7

Integration via Carthage should work for macOS, iOS, tvOS, and watchOS targets.

Manually

Clone the repository and add or copy SortedArray.swift to your project. It has no dependencies.

Dependencies

None.

License

MIT license.

sortedarray's People

Contributors

capnslipp avatar divinedominion avatar kareman avatar klaaspieter avatar ole avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

sortedarray's Issues

Add a shell script for running the Linux tests locally

I'd like to have a script that lets me spin up a few Docker containers (one per supported Swift version) and run the tests on Linux with a single command. We can use the existing travis-build-script.sh for inspiration.

Invalid Bundle - Disallowed LLVM instrumentation

Apple has a new automatic check when validating the binary that was built using Xcode 9 / iOS 11 SDK. If the binary contains some code coverage instrumentation, it will be rejected. The full message is:

Invalid Bundle - Disallowed LLVM instrumentation. Do not submit apps with
LLVM profiling instrumentation or coverage collection enabled. Turn off
LLVM profiling or code coverage, rebuild your app and resubmit the app.

cocopods?

Can we have this available on cocoa pods as well please?

`last(where:...)` uses `firstIndex(where:...)`

    public func last(where predicate: (Element) throws -> Bool) rethrows -> Element? {
        guard let index = try firstIndex(where: predicate) else { return nil }
        return self[index]
    }

presumably should be lastIndex(where:...)

Sort position vs element equality

I was surprised to find that the sort position of an element is also being used to determine element equality. This is can be seen with the following test case:

    func testEqualityVsSortPosition() {
        struct Item: Equatable {
            let id: String
            let name: String
        }

        let item1 = Item(id: "1", name: "Bumble")
        let item2 = Item(id: "2", name: "Bumble") // two items with same name, but not Equality
        let item3 = Item(id: "3", name: "Fumble")
        let item4 = Item(id: "4", name: "Grumble")

        // array is missing item 2
        var array = SortedArray(unsorted: [item1, item3, item4], areInIncreasingOrder: { $0.name < $1.name })

        // correctly find item 1
        XCTAssertTrue(array.contains(item1))       // passes
        // incorrectly find item 2
        XCTAssertFalse(array.contains(item2))      // fails

        XCTAssertNil(array.index(of: item2))       // fails
        XCTAssertNil(array.anyIndex(of: item2))    // fails
        XCTAssertNil(array.firstIndex(of: item2))  // fails
        XCTAssertNil(array.lastIndex(of: item2))   // fails

        let countBefore = array.count
        array.remove(item2)
        let countAfter = array.count
        XCTAssertEqual(countBefore, countAfter) // fails
    }

I would expect methods like remove(_ element: Element) to only remove if the elements are actually equal, not just if they're sorted into the same place. This method has the same signature as the one on Set, but behaves very differently.

A workaround is to define the sort function to take equality into account. I don't believe it's intuitive to consider objects sorted to the same index as also being Equal. At a minimum this should be better documented. I'd suggest to either update the functionality to take Equatable conformance into account, or change the method names to make it clear its acting on sort order not equality.

Nitpick: Isn't array insertion always expensive?

// This should be O(1) if the element is to be inserted at the end,
// O(_n) in the worst case (inserted at the front).
_elements.insert(newElement, at: index)

The comment suggests that insertion in Swift arrays is sometimes cheaper than a full copy.

The standard doc is not helpful; they only report the "Big-Oh".

Apparently, at least back in 2016, appending elements is cheap if contiguous memory can be allocated after the current buffer; if not, there'd be a full copy.

It seems reasonable to assume that insertion could be similarly sped up, for a total cost of

  • T_search(n) + T_extend + (n-i)*T_swap in the good case, and
  • T_search + T_copy(n) in the bad case (no matter at which index we insert).

search algorithm doesn't take duplicate keys into account

Hello,
I think the algorithm :

fileprivate func search(for newElement: Element) -> Match<Index> {
    guard !isEmpty else { return .notFound(insertAt: endIndex) }
    var left = startIndex
    var right = index(before: endIndex)
    while left <= right {
        let dist = distance(from: left, to: right)
        let mid = index(left, offsetBy: dist/2)
        let candidate = self[mid]

        if areInIncreasingOrder(candidate, newElement) {
            left = index(after: mid)
        } else if areInIncreasingOrder(newElement, candidate) {
            right = index(before: mid)
        } else {
            // If neither element comes before the other, they _must_ be
            // equal, per the strict ordering requirement of `areInIncreasingOrder`.
            return .found(at: mid)
        }
    }
    // Not found. left is the index where this element should be placed if it were inserted.
    return .notFound(insertAt: left)
}

Doesn't take into account the case where duplicate keys are present. In particular, in calculating the mid point, it'll give the index value of the first occurence of newElement == candidate, not the smallest index.

As a result, enumerating all keys verifying k == 0 (for example), will fail. One has to find the lowest value for which areInIncreasingOrder(candidate, newElement) == true and areInIncreasingOrder(newElement, candidate + 1) == false.

If I find a quick solution, I'll let you know.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.