Карта массивов, Свифт - PullRequest
       26

Карта массивов, Свифт

4 голосов
/ 18 апреля 2020

У меня есть собственный класс Rules.

class Rules: NSCoding {

var x: String?
var y: Double?

override func mapping(map: Map) {
    self.x     <- map["x"]
    self.y     <- map["y"]
}

В моей viewModel мне нужно создать правила объекта и передать 1 на 1 элементы двух массивов. Первый массив состоит из 3 строк, второй массив имеет некоторый Double (больше 3 !!). Это то, что я пробовал до сих пор:

let xValues = ["String1", "String2", "String3"]
let yValues = [1.0, 2.0, 1.5, 2.5, 5.1, 6.0, 8.0]

let rules = zip(xValues, yValues).map {
    Rules(x: "\($0.0)", y: $0.1)
}

Проблема с этим (я полагаю) заключается в том, что мой В объекте rules есть дублирующаяся строка, а иногда и больше, чем в моем массиве xValues. (Возможно, я делаю что-то не так в другом месте ...)

Мне нужно пропустить ровно три строки и число Double, которое отличается, скажем, 6 double.

Ответы [ 2 ]

2 голосов
/ 18 апреля 2020

Поскольку zip возвращает кортежи только для тех индексов, у которых оба входных массива имеют значения, вам понадобится метод, который вместо этого заполняет меньший массив, например:

func zipFill<T, U>(_ arr1: [T], _ arr2: [U]) -> [(T?, U?)] {
    let c1 = arr1.count
    let c2 = arr2.count
    let count = max(c1, c2)

    var result = [(T?, U?)]()

    for i in 0..<count {
        if i < c1 && i < c2 {
            result.append((arr1[i], arr2[i]))
        } else if i >= c1 {
            result.append((nil, arr2[i]))
        } else if i >= c2 {
            result.append((arr1[i], nil))
        }
    }

    return result
}

let xValues = ["String1", "String2", "String3"]
let yValues = [1.0, 2.0, 1.5, 2.5, 5.1, 6.0, 8.0]

let rules = zipFill(xValues, yValues).map {
    Rules(x: $0.0, y: $0.1)
}

print(rules)  
// [ {x "String1", y 1}, {x "String2", y 2}, {x "String3", y 1.5},
//   {x nil, y 2.5}, {x nil, y 5.1}, {x nil, y 6}, {x nil, y 8} ]
1 голос
/ 18 апреля 2020

Почему бы вам просто не удалить дубликаты перед созданием правил?

Определить расширение c для удаления дубликатов:

extension RangeReplaceableCollection {

    func removingDuplicates<E>(keyPath path: KeyPath<Element, E>) -> Self 
        where E: Hashable 
    {
        var seen = Set<E>()
        seen.reserveCapacity(count)
        var new = self
        new.removeAll { element -> Bool in
            if seen.contains(element[keyPath: path]) {
                return true
            } else {
                seen.insert(element[keyPath: path])
                return false
            }
        }
        return new
    }

}

Затем удалить дубликаты перед архивированием:

let xValues = ["String1", "String2", "String3"].removingDuplicates(keyPath: \.self)
let yValues = [1.0, 2.0, 1.5, 2.5, 5.1, 6.0, 8.0].removingDuplicates(keyPath: \.self)

let rules = zip(xValues, yValues).map {
    Rules(x: $0.0, y: $0.1)
}

Tidbit: вам не нужно использовать строковую интерполяцию для аргумента x, потому что параметр $0.0 уже является String.

...