返回指定值出现在集合中的第一个索引

时间:2019-11-05 23:08:04

标签: ios arrays swift class dictionary

我正在努力从下面的代码中检索城市索引。

我的完整代码是

国家/地区:

import UIKit

class Country { 
    var name: String 
    var cities: [City]

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

Class City:

import UIKit

class City { 
    var name: String 

    init(name:String) {
        self.name = name
    }
}

ViewController:

class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
    @IBOutlet weak var pickerView: UIPickerView!
    @IBOutlet weak var countryLbl: UILabel!

    var countries = [Country]()
    let states = ["CA","GA","FL","NY","NV","TX"]

    override func viewDidLoad() {
        pickerView.delegate = self
        pickerView.dataSource = self

        countries.append(Country(name: "UK", cities: [City(name: "London"),City(name: "Manchester"), City(name: "Bristol")]))
        countries.append(Country(name: "USA", cities: [City(name: "New York"),City(name: "Chicago")]))
        countries.append(Country(name: "China", cities: [City(name: "Beijing"),City(name: "Shanghai"), City(name: "Shenzhen"), City(name: "Hong Kong")]))

        super.viewDidLoad()

        // For the constant "states" I can use firstIndex to retrieve state index
        let stateIndex = states.firstIndex(of: "NY")
        print("This is the retrieved State index \(stateIndex)")
        // Print above shows "This is the retrieved State index Optional(3)" that is right

        // Retrieve City index
    }

    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 2
    }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        if component == 0 {
            return countries.count
        } else  {
            let selectedCountry = pickerView.selectedRow(inComponent: 0)
            return countries[selectedCountry].cities.count
        } 
    }

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        if component == 0 {
            return countries[row].name
        } else {
            let selectedCountry = pickerView.selectedRow(inComponent: 0)
            return countries[selectedCountry].cities[row].name
        } 
    }

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        pickerView.reloadAllComponents

        let selectedCountry = pickerView.selectedRow(inComponent: 0)
        let selectedCity = pickerView.selectedRow(inComponent: 1)
        let cityR = countries[selectedCountry].cities[selectedCity].name

        countryLbl.text = "The right answer was: \(selectedCountry) in \(cityR)"

    }
}

如您所见,对于常规常数,它可以按预期工作。

我需要为纽约市做同样的事情。对于特定的州,我需要检索城市指数。 问题在于,当我基于模板和类构建它时,无法使用firstIndex来定位城市索引。

我该怎么做?例如,如何检索“芝加哥”索引?

2 个答案:

答案 0 :(得分:1)

尚不清楚您是否需要包含城市的国家/地区索引,在这种情况下可以使用

func index(of city: String, in countries: [Country]) -> Int? {
   countries.firstIndex{$0.cities.contains{$0.name == city}}
}

然后使用它

let indexOfCountryWithCity = index(of: "Chicago", in: countries)

或者如果您想要该国家在城市列表中的城市索引,在这种情况下,您需要添加第二步

func index(of city: String, in countries: [Country]) -> (countryIndex: Int?, cityIndex: Int?) {
   guard let countryIndex = countries.firstIndex(where: {$0.cities.contains{$0.name == city}}) 
         else {return (nil, nil)}
   let cityIndex = countries[countryIndex].cities.firstIndex{$0.name == city}
   return (countryIndex, cityIndex)
}

,该方法现在将返回一个元组,其中包含country数组中countries的索引和该国家的city数组中cities的索引。

用法是:

if let result = index(of: "Chicago", in: countries), let countryIndex = result.countryIndex, let cityIndex result.cityIndex {
   //do something with countryIndex & cityIndex
}

请注意,返回值将是可选的,以应对不存在的城市,因此需要在上方展开。

更新,因为已阐明问题。需要获取已经提供了国家和城市名称的cityIndex和countryIndex

func indexOf(city: String, inCountry country: String, in countries: [Country]) -> (countryIndex: Int, cityIndex: Int)? {
   guard let countryIndex = countries.firstIndex(where: {$0.name == country}), let cityIndex = countries[countryIndex].cities.firstIndex(where: {$0.name == city}) else {return nil}
   return (countryIndex, cityIndex)
}

请注意,元组现在是可选的,而不是字段,因此更容易解包:

if let indexes = indexOf(city: "Bristol", inCountry: "UK", in: countries) {
  //do something with indexes.countryIndex and indexes.cityIndex
}

答案 1 :(得分:0)

一种实现方法是

guard let countryUSA = countries.filter({ $0.name == "USA"}).first else { return }
let cityIndex = countryUSA.cities.firstIndex(where: { $0.name == "Chicago" })

您还可以将国家和城市名称作为变量传递,而不用明确地说出USAChicago