判断数组是否包含 swift 中另一个数组的一个或多个元素

Determine whether array contains one or more elements of another array in swift

我有以下代码 returns 放在用户当前位置附近

import UIKit
import GooglePlaces
import CoreLocation

struct GlobalVariables {
    static var acceptedEstablishments = ["bakery", "bar", "cafe", "food", "meal_takeaway", "meal_delivery", "night_club", "restaurant", "school", "university"]
}

class ViewController: UIViewController, CLLocationManagerDelegate {

    var placesClient: GMSPlacesClient!
    var locationManager: CLLocationManager!

    // Add a pair of UILabels in Interface Builder, and connect the outlets to these variables.
    @IBOutlet var nameLabel: UILabel!
    @IBOutlet var addressLabel: UILabel!


    override func viewDidLoad() {
        super.viewDidLoad()
        placesClient = GMSPlacesClient.shared()

        locationManager = CLLocationManager()
        locationManager.delegate = self
        locationManager.requestWhenInUseAuthorization()
    }

    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        if status == .authorizedWhenInUse {
            locationManager.desiredAccuracy = kCLLocationAccuracyBest
            locationManager.startUpdatingLocation()
        }
    }

    // Add a UIButton in Interface Builder, and connect the action to this function.
    @IBAction func getCurrentPlace(_ sender: UIButton) {

        placesClient.currentPlace(callback: { (placeLikelihoodList, error) -> Void in
            if let error = error {
                print("Pick Place error: \(error.localizedDescription)")
                return
            }

            if let placeLikelihoodList = placeLikelihoodList {
                for likelihood in placeLikelihoodList.likelihoods {
                    let place = likelihood.place
                    // only return places that are relevant to me
                    for placeType in place.types {
                        if (GlobalVariables.acceptedEstablishments.contains(placeType)) {
                            print("Current place name: \(place.name)")
                            print("Place type: \(placeType)")
                        }
                    }

                }
            }
        })
    }
}

place.types 在底部的回调函数中 returns 每个地点实例的字符串数组,看起来像这样:

["health", "point_of_interest", "establishment"]

我有一个全局字符串数组,其中还包含 bakerybar 等标签。

当用户按下按钮时,回调函数被触发并returns根据附近的位置进行放置。

输出看起来像这样:

Current place name: LOCAL SUPERMARKET
Place type: food
Current place name: LOCAL GRILL
Place type: cafe
Current place name: LOCAL GRILL
Place type: food
Current place name: LOCAL SCHOOL
Place type: school
Current place name: LOCAL TAKEAWAY
Place type: meal_takeaway
Current place name: LOCAL TAKEAWAY
Place type: restaurant
Current place name: LOCAL TAKEAWAY
Place type: food

同一个机构被重复多次,因为一个机构有多个关联标签。

例如:

place.typesLOCAL TAKEAWAY 的返回数组是:["meal_takeaway", "restaurant", "food"]

并且因为我的 GlobalVariables.acceptedEstablishments 数组包含所有这三个字符串,所以 print 命令将被执行三次。

如果 place.types 数组包含一个或多个匹配字符串,如何修改此代码使其只显示一次建立?我似乎无法找到解决方案。

Swift 数组 class 允许重复项。 Set class 没有。您可以在 Array 上创建一个扩展,它有一个方法 uniqueItems 可以去除重复项。请注意,数组中的项目必须是 Hashable 才能使其工作。

下面是扩展名。 (不是我的代码 - 来自 another SO post

extension Array where Element: Hashable {
    var uniqueItems: Array  {
        var set = Set<Element>()
        return flatMap { set.insert([=10=]).inserted ? [=10=] : nil }
    }
}

密钥正在使用 Set,不会有重复项。 Set 是一个集合 class ,可以像数组一样使用。你可以遍历它,它有countmapfiltercontains

let acceptedPlaces: Set = ["home", "pub", "hospital"]
let availablePlaces: Set = ["home", "pub", "mountains"]
let inBoth = acceptedPlaces.intersection(availablePlaces) // ["home", "pub"]

您可以轻松地从 Arrays let someSet = Set(someArray) 创建 Sets,反之亦然 let someArray = Array(someSet)。您可能还想看看 Set 的以下函数:unionsubstractisSuperSetisSubset.

您还可以使用集合:

if !Set(place.types).intersection(GlobalVariables.acceptedEstablishments).isEmpty
{
  // there is at least one common element
}

如果你能负担得起 GlobalVariables.acceptedEstablishments 一个集合,那么条件会更有效,可以写成:

if !GlobalVariables.acceptedEstablishments.intersection(places.types).isEmpty
{
  // there is at least one common element
}

无论哪种情况,places.types 本身都不需要是集合。

使用isDisjoint(with:):

if !Set(place.types).isDisjoint(GlobalVariables.acceptedEstablishments) {
    // There is at least one common element
}