将对象数组与里面的子对象数组合并

Posted

技术标签:

【中文标题】将对象数组与里面的子对象数组合并【英文标题】:Merge object arrays with child object arrays inside 【发布时间】:2021-04-06 21:22:08 【问题描述】:

我有两个数组(CountyCity 都符合 Comparable):

let array1 = [
  Country(code: "US", cities: [
    City(name: "Dallas"),
    City(name: "New York")
  ]),
  Country(code: "UK", cities: [
    City(name: "London"),
    City(name: "Manchester")
  ])
]

let array2 = [
  Country(code: "DE", cities: [
    City(name: "Munich"),
    City(name: "Leipzig")
  ]),
  Country(code: "US", cities: [
    City(name: "Seattle")
    City(name: "New York")
  ]),
  Country(code: "UK", cities: [
    City(name: "London"),
    City(name: "Birmingham"),
    City(name: "Manchester")
  ])
]

到目前为止,我设法将仅比较国家代码的那些结合起来:

let mergedArray = array1 + array2.filter  country in
  return !array1.contains  $0.code == country.code 

我如何解释里面那些重复的城市?基本上得到这个:

let mergedArray = [
  Country(code: "DE", cities: [
    City(name: "Munich"),
    City(name: "Leipzig")
  ]),
  Country(code: "US", cities: [
    City(name: "Dallas"),
    City(name: "Seattle")
    City(name: "New York")
  ]),
  Country(code: "UK", cities: [
    City(name: "London"),
    City(name: "Birmingham"),
    City(name: "Manchester")
  ])
]

也尝试过(没有为英国添加那些额外的城市):

func combine<T>(_ arrays: Array<T>?...) -> Set<T> 
  return arrays.compactMap$0.compactMapSet($0).reduce(Set<T>())$0.union($1)

并尝试过,但完全没有运气(很多重复):

let mergedArray = array1 + array2.filter  country in
  return !array1.contains  $0.code == country.code   ||
    (!array1.contains(where:  $0.cities?.contains(where: country.cities!.contains) as! Bool ))

【问题讨论】:

我会将第一个数组加载到字典中,以国家/地区名称为键。迭代你的第二个数组。检查字典是否有国家的条目,如果没有,只需将国家添加到字典中。如果是这样,您需要合并城市。最后将字典转换回数组。要合并城市数组,您可以将每个数组转换为一个集合,然后将两个集合的并集转换回一个数组。 你想尝试尽可能少的线条吗?如果不是,您不能只使用ForEach 遍历array1,并且对于与array2 中的代码匹配的所有国家/地区,只需将城市对象添加到array1 中的Country 对象中。在末尾附加所有“不匹配”的国家/地区代码 是的,@Paulw11 和 @Rikh 的好主意,但如果可能的话,我只想要最干净的解决方案。当然,我可以手动遍历数组并使用 forif 来完成,但这不会很有趣:) 【参考方案1】:

你能让City符合Hashable吗?如果是这样,试试这个:

var dict = [String: Set<City>]() // code -> cities

for country in array1 + array2 
    dict[country.code, default: Set<City>()].formUnion(country.cities)


// convert back to array
let mergedArray = dict.map  code, cities in
    Country(code: code, cities: Array(cities))

【讨论】:

啊!那是天才 :) 所以基本上Set 中的项目不能有重复项,因此可以完美运行。基本上4行代码!谢谢!

以上是关于将对象数组与里面的子对象数组合并的主要内容,如果未能解决你的问题,请参考以下文章

使用值将数组中对象的属性合并在一起并删除重复项

JS----对象的合并与克隆与数组的深浅克隆

如何将同一属性上的数组和对象“合并/合并”到平面数组中(使用Javascript)?

将数组合并到对象到 MongoDB

vue.js数组追加合并与对象追加合并

将二维数组合并到对象数组中