【问题标题】:Array map, Swift数组映射,斯威夫特
【发布时间】:2020-07-31 19:55:39
【问题描述】:

我有一个自定义规则类。

class Rules: NSCoding {

var x: String?
var y: Double?

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

在我的 viewModel 中,我需要创建一个对象规则并将两个数组的元素一一传递。第一个数组由 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)
}

这个问题(我猜)是我的规则对象有一些重复的字符串,或者有时比我的 xValues 数组中的更多。 (我可能在其他地方做错了什么......)

我需要准确地传递三个字符串,以及一个不同的 Double 数量,比如 6 个 double。

【问题讨论】:

  • 我应该是 y: $1.0 不?
  • 我收到此错误:“Double”类型的值没有成员“0”
  • 试试 x: $0, y:$1
  • 仍然有重复的东西......我无法显示输出,因为我将这个对象传递给了一个函数(如果我以不同的方式传递数据(没有重复),这个函数可以工作)但是这次我需要这样做...
  • 你能提供预期的输出吗?

标签: ios arrays swift dictionary nscoding


【解决方案1】:

由于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} ]

【讨论】:

    【解决方案2】:

    为什么不在创建规则之前删除重复项?

    定义一个通用扩展来删除重复项:

    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)
    }
    

    花絮:x 参数不需要使用字符串插值,因为参数$0.0 已经是String

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-22
      • 2017-03-24
      • 1970-01-01
      • 2016-02-08
      • 2017-11-13
      • 2015-08-19
      • 2014-09-11
      • 1970-01-01
      相关资源
      最近更新 更多