skip to Main Content

I want to add NumPy like functionality to a Swift array where you can use the + or – operators to add/subtract a Double to every element of a numeric Array and return a new Array with the new elements as [Double]. Here is how I have implemented it in 2 extensions for Int and Floating point types:

extension Array where Element: BinaryInteger {
    static func + (array: Self, num: Double) -> [Double]
    {
        return array.map{Double($0) + num}
    }
    
    static func - (array: Self, num: Double) -> [Double]
    {
        return array.map{Double($0) - num}
    }
}

extension Array where Element: BinaryFloatingPoint {
    static func + (array: Self, num: Double) -> [Double]
    {
        return array.map{Double($0) + num}
    }
    
    static func - (array: Self, num: Double) -> [Double]
    {
        return array.map{Double($0) - num}
    }
}

As you can see there is a lot of duplicate code here. Is there a better way to implement this?

I tried this but it doesn’t work:

extension Array where Element: Numeric {
    static func + (array: Self, num: Double) -> [Double]
    {
        return array.map{Double($0) + num}
    }
    
    static func - (array: Self, num: Double) -> [Double]
    {
        return array.map{Double($0) - num}
    }
}

The compiler complains at line Double($0) since Double doesn’t have initializer for Numeric.

2

Answers


  1. Chosen as BEST ANSWER

    I decided to check type of Element and force typecast instead:

    extension Array where Element: Numeric {
        static func + (array: Self, num: Decimal) -> [Decimal]
        {
            if let first = array.first {
                switch first {
                case is Int:
                    return array.map{Decimal($0 as! Int) + num}
                case is Double:
                    return array.map{Decimal($0 as! Double) + num}
                case is Decimal:
                    return array.map{$0 as! Decimal + num}
                default:
                    break
                }
            }
            
            return []
            
        }
        
        static func - (array: Self, num: Decimal) -> [Decimal]
        {
            if let first = array.first {
                switch first {
                case is Int:
                    return array.map{Decimal($0 as! Int) - num}
                case is Double:
                    return array.map{Decimal($0 as! Double) - num}
                case is Decimal:
                    return array.map{$0 as! Decimal - num}
                default:
                    break
                }
            }
            
            return []
            
        }
        
        static func / (array: Self, num: Decimal) -> [Decimal]
        {
            if let first = array.first {
                switch first {
                case is Int:
                    return array.map{Decimal($0 as! Int) / num}
                case is Double:
                    return array.map{Decimal($0 as! Double) / num}
                case is Decimal:
                    return array.map{$0 as! Decimal / num}
                default:
                    break
                }
            }
            
            return []
            
        }
    }
    

  2. Why use Double at all? You’re just introducing potential precision issues for integer types that have perfect precision over integers

    extension Array where Element: Numeric {
        static func + (array: Self, num: Element) -> [Element] {
            return array.map { $0 + num }
        }
        
        static func - (array: Self, num: Element) -> [Element] {
            return array.map { $0 - num }
        }
    }
    
    print([1, 2, 3] + 10) // => [11, 12, 13]
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search