【问题标题】:Merging two arrays of structures using iOS swift使用iOS swift合并两个结构数组
【发布时间】:2018-06-19 09:50:39
【问题描述】:

如何根据结构(名称)中的键合并两个(第一个和第二个)结构数组。合并时,我需要用第二个数组元素替换第一个数组的现有元素,如果该元素中有任何值发生变化。

struct Example: Codable {
    var name: String
    var dob: String
    var address: String
}

var first: [Example] = []
var second: [Example] = []

first.append(Example(name: "Arun", dob: "01-01-1994", address: "Tirupati"))
first.append(Example(name: "Balaji", dob: "01-01-1994", address: "Tirupati"))
first.append(Example(name: "Prasanth", dob: "01-01-1994", address: "Tirupati"))
    first.append(Example(name: "Satish", dob: "01-01-1994", address: "Tirupati"))


second.append(Example(name: "Arun", dob: "01-01-1994", address: "Kadapa"))
second.append(Example(name: "Balaji", dob: "01-01-1994", address: "Tirupati"))
second.append(Example(name: "Prasanth", dob: "01-01-1994", address: "Tirupati"))
second.append(Example(name: "Harsha", dob: "01-01-1994", address: "Tirupati"))

/*    let merged: [Example] = merge(first, second, with: name)
'merged' must contain four elements Arun, Balaji, Prasanth, Satish, Harsha, 
but Arun details are from 'second', because 'address' changed in second. So, I need element from 'second'*/

请告诉我简单的方法,谢谢。

【问题讨论】:

  • 是的,但连接与合并不同。连接可能有重复。
  • 顺序重要吗?否则可能是(NS)SetEquatable 或类似的东西,还是NSOrderedSetstackoverflow.com/a/44228470/1801544(在Equatable之后?)
  • 是否保证second包含first的所有元素?或者first 中并非所有元素都存在于second 中?对于您问题中的示例,merged 应该只是 second
  • @DávidPásztor 抱歉,我一定是误会了。不过,这应该很容易研究。

标签: ios arrays swift merge structure


【解决方案1】:
import Foundation

struct Example: Codable {
    var name: String
    var dob: String
    var address: String
}

var first: [Example] = []
var second: [Example] = []

first.append(Example(name: "Arun", dob: "01-01-1994", address: "Tirupati"))
first.append(Example(name: "Balaji", dob: "01-01-1994", address: "Tirupati"))
first.append(Example(name: "Prasanth", dob: "01-01-1994", address: "Tirupati"))

second.append(Example(name: "Arun", dob: "01-01-1994", address: "Kadapa"))
second.append(Example(name: "Balaji", dob: "01-01-1994", address: "Tirupati"))
second.append(Example(name: "Prasanth", dob: "01-01-1994", address: "Tirupati"))
second.append(Example(name: "Harsha", dob: "01-01-1994", address: "Tirupati"))

first = second + first.filter { element in
    return !second.contains { $0.name == element.name }
}

[{name "Arun", dob "01-01-1994", address "Kadapa"},
{name "Balaji", dob "01-01-1994", 地址 "Tirupati"},
{name "Prasanth", dob "01-01-1994", 地址 "Tirupati"},
{name "Harsha", dob "01-01-1994", 地址“蒂鲁帕蒂”}]

【讨论】:

  • 您是否真的尝试过在问题中使用Example 类型?这根本不是 OP 想要做的。
  • 如果您不确定代码的作用,请不要发布答案。您的代码仍然没有提供预期的输出。它只需要两个数组的并集,根本不处理重复的名称......
【解决方案2】:

如果合并数组中元素的顺序无关紧要,那么您可以使用 将每个名称映射到具有该名称的(最近的)元素的字典 (类似于user2760845 suggested)。

var dict: [String: Example] = [:]
for elem in first { dict[elem.name] = elem }
for elem in second { dict[elem.name] = elem }
let merged = Array(dict.values)

遍历第二个数组会覆盖同名的条目 从第一个数组。

或者,作为(混淆的?)单行:

let merged = Array(Dictionary([first, second].joined().map { ($0.name, $0)}, uniquingKeysWith: { $1 }).values)

【讨论】:

  • 单线可能是最简单有效的方法。
  • @ParthAdroja:这实际上取决于元素的数量,也许它们的大小,以及存在多少“重复”。与stackoverflow.com/a/50926135/1187415 一样,它避免了线性搜索,这可能对大型数组有利。对于中小型阵列,各种答案中给出的所有解决方案之间可能没有显着差异。
  • 完全同意你的看法。
【解决方案3】:

下面是一个简单但非常高效的实现。如果您需要保持元素的相对顺序,则需要对解决方案进行一些调整。

var secondDict = [String: Example]()
var merge = [Example]()
for eg2 in second {
    secondDict[eg2.name] = eg2
}
for eg1 in first {
    if let eg2 = secondDict.removeValue(forKey: eg1.name) {
        merge.append(eg2)
    } else {
        merge.append(eg1)
    }
}
for eg2 in secondDict.values {
    merge.append(eg2)
}
// 'merge' is the merged array

【讨论】:

    【解决方案4】:

    您可以通过使用以下函数使用第二个数组中的信息更新重复名称来合并两个 Example 数组。如果second 不包含first 的所有元素,此功能也有效。

    func merge(first: [Example], second: [Example]) -> [Example] {
        var secondCopy = second
        let updatedFirst = first.map({ person -> Example in
            let updatedIndex = secondCopy.index(where: {$0.name == person.name})
            if let updatedIndex = updatedIndex {
                let updated = secondCopy[updatedIndex]
                secondCopy.remove(at: updatedIndex)
                return updated
            } else {
                return person
            }
        })
        return updatedFirst + secondCopy
    }
    
    let merged = merge(first: first, second: second)
    

    [{name "Arun", dob "01-01-1994", address "Kadapa"},

    {name "Balaji", dob "01-01-1994", address "Tirupati"},

    {name "Prasanth", dob "01-01-1994", address "Tirupati"},

    {姓名“Harsha”,出生日期“01-01-1994”,地址“Tirupati”}]

    【讨论】:

      【解决方案5】:

      你可以试试这个,不知道是不是你需要的。

      struct Example: Codable, Hashable {
      
          var hashValue: Int {
              return self.name.hashValue
          }
      
          var name: String
          var dob: String
          var address: String
      }
      
      func ==(lhs: Example, rhs: Example) -> Bool {
          return lhs.name == rhs.name
      }
      
      func merge(first: [Example], second: [Example]) -> [Example] {
          return Array(Set(second).union(first))
      }
      
      let merged = merge(first: first, second: second) // is this what you need?
      

      【讨论】:

      • 如果不确定答案,请向 OP 提问。问题清楚地表明 OP 不仅需要联合,还希望使用 second 的属性更新重复值。
      • hmm 我认为 OP 希望在最终数组中包含所有 4 个对象,而不仅仅是更新第一个数组中的前 3 个对象。我的错。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-29
      • 2020-12-15
      • 1970-01-01
      • 2015-02-09
      • 2016-07-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多