emmalyx
emmalyx

Reputation: 2356

Can't sort array: "Ambiguous reference to member '<'"

extension Array where Element: Numeric {
    func closest(to givenValue: Element) -> Element {
        let sorted = self.sorted(by: <)

        let over = sorted.first(where: { $0 >= givenValue })!
        let under = sorted.last(where: { $0 <= givenValue })!

        let diffOver = over - givenValue
        let diffUnder = givenValue - under

        return (diffOver < diffUnder) ? over : under
    }
}

In line 3 of this example code, Xcode gives me the incomprehensible error message Ambiguous reference to member '<', along with this great list:

list of like a dozen "Found this candidate" entries

What am I supposed to do here? I just want this array to get sorted.

Upvotes: 2

Views: 405

Answers (4)

JillevdW
JillevdW

Reputation: 1137

I was just running into a similar problem stemming from the type inference when chaining multiple higher order functions (sort, map, etc), when I found this post and I couldn't help but notice the inefficiency of your function.

Here is an example of how you can implement this same function using binary search, massively reducing the time it takes to execute on large datasets:

extension Array where Element: Numeric & Comparable {
    func closest2(to target: Element) -> Element {
        if target <= self[0] {
            return self[0]
        }
        if target >= self[count - 1] {
            return self[count - 1]
        }

        var i = 0
        var j = count
        var mid = 0

        while i < j {
            mid = (i + j) / 2

            if self[mid] == target {
                return self[mid]
            }

            if target < self[mid] {

                if mid > 0 && target > self[mid - 1] {
                    return getClosest(val1: self[mid - 1], val2: self[mid], target: target)
                }

                j = mid

            } else {
                if mid < count - 1 && target < self[mid + 1] {
                    return getClosest(val1: self[mid], val2: self[mid + 1], target: target)
                }

                i = mid + 1
            }

        }

        return self[mid]
    }

    private func getClosest(val1: Element, val2: Element, target: Element) -> Element {
        return target - val1 > val2 - target ? val2 : val1
    }
}

Upvotes: 0

Ankit Jayaswal
Ankit Jayaswal

Reputation: 5689

Problem is that you have defined your Element as Numeric only where > will work with Comparable.

Do it as:

extension Array where Element: Numeric, Element: Comparable {
    func closest(to givenValue: Element) -> Element {
        //... your code here ...
    }
}

Upvotes: 1

flogram_dev
flogram_dev

Reputation: 42858

You have to declare Element to be Comparable:

extension Array where Element: Numeric & Comparable {

Upvotes: 7

shikai ng
shikai ng

Reputation: 135

In

let sorted = self.sorted(by: <)

you're not giving a boolean function for the function to use. Maybe try replacing it with :

let sorted = self.sorted(by: { $0 < $1 })

Upvotes: 2

Related Questions