Инициировать FloatingPoint из строки - PullRequest
1 голос
/ 31 марта 2020

Я пытаюсь преобразовать двумерный массив String s в мой пользовательский шаблон c type Matrix:

func convert(_ arr: [[String]]) -> Matrix<Element> {
    var m: Matrix<Element> = Matrix()
    for row in arr {
        var v: [Element] = []
        for e in row {
            let convE: Element = Element(string: e) // right here I'd like to implement something like that: Element(string: e)
            v.append(convE)
        }
        m.vectors.append(Vector(v))
    }
    return m
}

Matrix.Element соответствует протоколу FloatingPoint. Скажите, пожалуйста, если вы sh увидите структуру Matrix, но я думаю, что я не реализовал ничего важного для этого вопроса, кроме того, что тип c Element generi Matrix соответствует FloatingPoint протокол.

Моя проблема в том, что я хочу, чтобы Element был похож на Float, Double ... (любой из типов FloatingPoint), но как я могу инициализировать FloatingPoint из строка? Я попытался:

extension FloatingPoint {
    init(string: String) {
        self.init(Int(string)!)
    }
}

, который, очевидно, работает только для таких строк, как "1", "2" ... а не "1.2", "3.541" и т. Д., Которые я хочу.

Редактировать: (@ Leo Dabus)

protocol DArray: Sequence {
    associatedtype Component: FloatingPoint
}
extension  DArray {
    static func * <T: DArray>(lhs: Self, rhs: T) -> Vector<Component> {
        let v = lhs as? Vector<Component> ?? rhs as! Vector<Component>
        let m = lhs as? Matrix<Component> ?? rhs as! Matrix<Component>
        return Vector(m.map { zip(v, $0).map(*).reduce(0, +) })
    }

    static func / <T: DArray>(lhs: Self, rhs: T) -> Vector<Component> {
        let v = lhs as? Vector<Component> ?? lhs as! Vector<Component>
        let m = lhs as? Matrix<Component> ?? lhs as! Matrix<Component>
        return Vector(m.map { zip(v, $0).map(/).reduce(0, +) })
    }
}

struct Vector<Component: FloatingPoint>: DArray {
    var components: [Component]
    var count: Int {
        return components.count
    }

    init(_ Components: [Component] = []) {
        self.components = Components
    }

    subscript(i: Int) -> Component {
        get {
            return components[i]
        } set {
            components[i] = newValue
        }
    }

    static func + (lhs: Self, rhs: Self) -> Self {
        return Vector(zip(lhs, rhs).map(+))
    }

    static func - (lhs: Self, rhs: Self) -> Self {
        return Vector(zip(lhs, rhs).map(-))
    }

    static func * (lhs: Self, rhs: Self) -> Self {
        return Vector(zip(lhs, rhs).map(*))
    }

    static func / (lhs: Self, rhs: Self) -> Self {
        return Vector(zip(lhs, rhs).map(/))
    }

    func empty(of length: Int) -> Self {
        return Vector(Array(repeating: 0, count: length))
    }
}

struct Matrix<Component: FloatingPoint>: DArray {
    var vectors: [Vector<Component>]
    var nRows: Int {
        return vectors.count
    }
    var nColumns: Int {
        guard !vectors.isEmpty else { return 0 }
        return vectors[0].count
    }
    var count: Int {
        return vectors.count
    }

    init(_ vectors: [Vector<Component>] = []) {
        self.vectors = vectors
    }

    subscript(r: Int) -> Vector<Component> {
        get {
        return vectors[r]
        }
        set {
            vectors[r] = newValue
        }
    }

    subscript(r: Int, c: Int) -> Component {
        get {
            return vectors[r][c]
        }
        set {
            vectors[r][c] = newValue
        }
    }
}

Кроме того, мои два struct соответствуют протоколу последовательности.

Ответы [ 2 ]

1 голос
/ 31 марта 2020

(Примечание: я ОП)

Что я придумал сейчас:

extension FloatingPoint {
    public init?(string: String) {
        if Self.self == Double.self {
            self = Double(string) as! Self
        } else if Self.self == Float.self {
            self = Float(string) as! Self
        } else if Self.self == Float80.self {
            self = Float80(string) as! Self
        } else {
            return nil
        }
    }
}

Это работает для моего варианта использования, но мне было интересно, насколько это хороший способ достижения того, что я ищу. Поэтому я был бы рад, если бы кто-то оценил мое решение. (@Leo Dabus)

0 голосов
/ 31 марта 2020

Можете ли вы попробовать что-то вроде этого:

extension FloatingPoint where Self == Double {
    init(string: String) {
        self.init(Double(string)!)
    }
}

extension FloatingPoint where Self == Float {
    init(string: String) {
        self.init(Float(string)!)
    }
}

это также должно работать

extension FloatingPoint {
    init(string: String) {
        self.init(Self(string)!)
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...