【问题标题】:How to merge multiple arrays in Swift?如何在 Swift 中合并多个数组?
【发布时间】:2019-05-23 11:51:56
【问题描述】:

我有几个类是这样的:

A类{} A1 类:A {} A2 类:A {} A3 类:A {} A4 类:A {} 类主{ 变量 a1 : A1 变量 a2 : A2 变量 a3s:[A3] var a4s:[A4] 函数 getAll() -> [A] { 返回 ([a1, a2] + a3s + a4s) } }

如果你看一下函数 getAll(),你会看到我尝试返回一个类型为基类 A 的所有对象的数组。但是,我总是得到错误:

“二元运算符'+(::)'不能应用于'[Any]'和'[a3s]'类型的操作数”

你知道在这种情况下正确的方法是什么吗?

【问题讨论】:

  • 那么,预期的输出是:一个包含四个数组中所有元素的数组,对吗?
  • 不是真正重复的问题。区别在于类型数组是基类的子类。
  • 这是另一个(只是为了好玩)return [[a1, a2], a3s, a4s].flatMap{ $0 as? [A] }.reduce([], +) 或更具冒险精神的return [[a1, a2], a3s, a4s].flatMap{ $0 as! [A] }
  • @Alladinian 不需要减少。强迫沮丧也是邪恶的。我设置了 SwiftLint 以将其标记为编译错误。

标签: ios arrays swift


【解决方案1】:

我猜这只是正确转换数组的问题,您可以这样做解决它:

func getAll() -> [A] {
    return ([a1, a2] as [A] + a3s as [A] + a4s)
}

只是为了好玩:如果你想动态解决它,你可以这样使用反射:

class A {}
class A1 : A {}
class A2 : A {}
class A3 : A {}
class A4 : A {}

class main {
    var a1 = A1()
    var a2 = A2()
    var a3s : [A3] = [A3()]
    var a4s : [A4] = [A4(), A4()]

    func getAll() -> [A] {
        var res = [A]()
        Mirror(reflecting:self).children.forEach {
            if let a = $0.value as? A {
                res.append(a)
            } else if let aArray = $0.value as? [A] {
                res.append(contentsOf: aArray)
            }
        }
        return res
    }
}

let all = main().getAll()
print(all) //A1, A2, A3, A4, A4

【讨论】:

  • @chipbk10 这很复杂:)
  • 这并不是一个复杂的用例。如果您声明一个具有正确类型的变量,就没有理由进行所有这些强制转换。
  • @Samah 当然,但是在问题中写的是Binary operator '+(::)' cannot be applied to operands of type '[Any]' and '[a3s]':我的回答试图与此类问题相关。
  • 回答问题和解决问题是有区别的。
【解决方案2】:

我猜这可能是一种更清洁的方式。

func getAll() -> [A] {
    let all: [[A]] = [[a1], [a2], a3s, a4s]
    return all.flatMap{$0}
}

这会创建一个数组数组,然后使用flatMap 将它们展平为一个数组。

【讨论】:

  • 甚至,你的代码更干净,但我想,计算成本很高。
  • 怎么这么贵? 4 元素数组上的平面图。
  • 但如果每个元素数组由 1000 个元素组成?
  • 那么你当然不应该追加数组。
  • 有点吹毛求疵,[[a1], [a2], a3s, a4s]可以写成[[a1, a2], a3s, a4s]
【解决方案3】:

问题在于编译器认为您正在尝试添加[Any][A3]。这是因为[a1, a2] is [Any]a3s is [A3]的类型。但是运营商+ 做不到。

正如其他人指出的那样,您可以将语句中的数组转换为 [A],以便 + 运算符可以完成他的工作。

由于您提到您有多个类,因此创建一个可以重用并且可以正确推断类型的函数可能是个好主意。

func merge<T>(_ array: [T]...) -> [T] {
    return array.flatMap { $0 }
}

func getAll() -> [A] {
    return merge([a1, a2], a3s, a4s)
}

【讨论】:

  • 对。这里的要点是[ClassA, ClassB] 的数组是[Any] 类型,除非你强制转换它,即使ClassAClassB 有一个共同的基类。如果在您的示例中,编译器会将[A1, A1] 的数组设为[A] 类型,那就太好了,但事实并非如此。
  • 没错,我在回答中遗漏了您的第一点。第二部分没看懂在merge(_:) 函数内运行array.forEach { print(type(of: $0)) } 将打印Array&lt;A&gt;。即使您将[a1, a1] 作为参数传递。
猜你喜欢
  • 2018-09-17
  • 2019-03-01
  • 2019-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-29
相关资源
最近更新 更多