根据对象字段减少对象数组

时间:2020-09-24 12:46:04

标签: arrays swift

我有一个Country对象和一个City对象

struct Country: {
  let name: String
  let countryCode: String
  let cities: [City]
  let population: Int

  init(name: String, countryCode: String, cities: [City], population: Int) { 
    self.name = name 
    self.countryCode = countryCode
    self.cities = cities
    self.population = population
  }
}

struct City {
  let id: Int
  let name: String
  let latitude: Double
  let longitude: Double
  let countryCode: String
  let population: Int
}

传入的JSON数据看起来像这样,它解码成[City]数组

{
   "cities":[
      {
         "id":1,
         "name":"Paris",
         "latitude":0,
         "logitude":0,
         "country_code":"FR",
         "population":0
      },
      {
         "id":2,
         "name":"Nice",
         "latitude":0,
         "logitude":0,
         "country_code":"FR",
         "population":0
      },
      {
         "id":3,
         "name":"Berlin",
         "latitude":0,
         "logitude":0,
         "country_code":"DE",
         "population":0
      },
      {
         "id":4,
         "name":"Munich",
         "latitude":0,
         "logitude":0,
         "country_code":"DE",
         "population":0
      },
      {
         "id":5,
         "name":"Amsterdam",
         "latitude":0,
         "logitude":0,
         "country_code":"NL",
         "population":0
      },
      {
         "id":6,
         "name":"Leiden",
         "latitude":0,
         "logitude":0,
         "country_code":"NL",
         "population":0
      }
   ]
}

如何有效地从[Country]数组创建[City]数组?我尝试使用reduce:into:,但不确定是我必须使用的。

我知道我可以使用一个空数组,一个接一个地添加/创建国家,然后搜索是否已经有一个并添加城市。对于我来说,这创建了可怕的代码。我觉得可以使用map或reduce函数解决这个问题。

到目前为止,我已经尝试过的

reduce:into:代码

func transformArrayOf(_ cities: [City]) -> [Country] {

  let empty: [Country] = []
        
  return cities.reduce(into: empty) { countries, city in
          
    let existing = countries.filter { $0.countryCode == city.countryCode }.first
    countries[existing].cities.append(city)
  }
}

编辑:

该函数仅获取[City]数组。因此,只能从此创建国家。

Dictionary(grouping:by:)map(_:)完美搭配!嵌套的for循环和if语句上有两行:)

Country的名称可以从国家/地区代码中解析出来

2 个答案:

答案 0 :(得分:0)

Dictionary(grouping:by:)的用途是

let citiesByCountryCode = Dictionary(grouping: cities, by: \.countryCode)

但是您需要使用单独的逻辑来创建国家/地区,因为它们包含的数据并非来自namecountryName(这些城市有何不同?)等城市。< / p>

答案 1 :(得分:0)

结合使用 Dictionary(grouping:by:) map(_:) 获得预期结果。

let countries = Dictionary(grouping: cities, by: { $0.countryCode }).map { (countryCode, cities) -> Country in
    return Country(name: "", countryCode: countryCode, countryName: "", cities: cities, population: cities.reduce(0) { $0 + $1.population })
}

由于namecountryName的值是未知的,因此我对两者都使用了空的String"")。

相关问题