Возвращает первый индекс, где указанное значение появляется в коллекции - PullRequest
0 голосов
/ 06 ноября 2019

Я изо всех сил пытаюсь получить индекс города из моего кода ниже.

Мой полный код

Страна класса:

import UIKit

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

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

Город класса:

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 ]

1 голос
/ 06 ноября 2019

Непонятно, нужен ли вам индекс страны, содержащей город, в этом случае это будет работать

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
}
0 голосов
/ 06 ноября 2019

Один из способов достижения этого -

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

Также вы можете передать название страны и города в качестве переменной, вместо того, чтобы явно сказать USA или Chicago

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...