Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Swift have a function similar to numpy.diff that calculates the difference between adjacent elements of an array

Tags:

swift

I'm trying to convert some Python code to Swift and wondering if there is an existing function to calculate the difference between successive elements in a Swift array. For example:

diff([1,3,5,6,10]) would return [2,2,1,4]
like image 712
Steve Conley Avatar asked Jun 04 '18 22:06

Steve Conley


People also ask

How do you find the difference between Numpy arrays?

The numpy module of Python provides a function called numpy. diff for calculating the nth discrete difference along the given axis. If 'x' is the input array, then the first difference is given by out[i]=x[i+1]-a[i]. We can calculate the higher difference by using diff recursively.

What does Numpy diff do?

In Python the numpy. diff() function is used to calculate the difference between values in an array along with a given axis. This method is available in the NumPy module package for calculating the nth discrete difference along the given axis.

Is Numpy diff the derivative?

numpy has a function called numpy. diff() that is similar to the one found in matlab. It calculates the differences between the elements in your list, and returns a list that is one element shorter, which makes it unsuitable for plotting the derivative of a function.


2 Answers

No, but it could be very easily implemented:

let a = [1, 3, 5, 6, 10]
zip(a.dropFirst(), a).map(-) // => [2, 2, 1, 4]

It's simple enough that it's probably not worth wrapping into a function, but if you insist:

extension Collection where Element: Numeric {
    func diff() -> [Element] {
        return zip(self.dropFirst(), self).map(-)
    }
}

[1, 3, 5, 6, 10].diff() // => [2, 2, 1, 4]

If you need the result to be lazily evaluated, you can do this:

extension Collection where Element: Numeric {
    func diff() -> AnyCollection<Element> {
        return AnyCollection(zip(self.dropFirst(), self).lazy.map(-))
    }
}
like image 190
Alexander Avatar answered Oct 03 '22 02:10

Alexander


You can use reduce(into:) combined with dropfirst to achieve what you want:

extension Collection where Element: SignedNumeric {
    func diff() -> [Element] {
        guard var last = first else { return [] }
        return dropFirst().reduce(into: []) {
            $0.append($1 - last)
            last = $1
        }
    }
}

Another option is to use map and defer:

extension Collection where Element: SignedNumeric {
    func diff() -> [Element] {
        guard var last = first else { return [] }
        return dropFirst().map { element in
            defer { last = element }
            return element - last
        }
    }
}

let arr = [1,3,5,6,10]
print(arr.diff())  // "[2, 2, 1, 4]\n"
like image 28
Leo Dabus Avatar answered Oct 03 '22 04:10

Leo Dabus