反向枚举以过滤掉数组中的类似对象

时间:2016-05-01 21:49:14

标签: arrays swift

我有一个CLLocations数组。我的目标是找到阵列中与位置相同的最后位置,然后删除以下所有对象。

示例:

[lat: 11.123, long: 11.123,
lat: 12.345, long: 123.123,
lat: 14.124, long: 14.124,
lat: 16.1661, long: 16.1616,
lat: 15.1515, long: 15.1515,
lat: 15.1515, long: 15.1515, //Remove
lat: 15.1515, long: 15.1515] //Remove 

我想改变它们存储的数组,而不是创建一个新数组。

到目前为止我的尝试:

 var reversedLocations = Array(locations.reverse())
            for (index,location) in reversedLocations.enumerate() {
                if index+1 <= reversedLocations.count-1 {
                    let distanceToNext = LocationInterface.sharedInterface.distanceBetweenLocations(first: location, last: locations[index+1])
                    if distanceToNext < 10 {
                        reversedLocations.removeAtIndex(reversedLocations.indexOf(location)!)
                        toDate = reversedLocations.first!.timestamp
                    }
                }
            }

但是这段代码令人困惑,我不确定它是最好的方法。这个函数只是乱七八糟,因为我改变了数组的枚举,所以索引不正确。是否有任何Array.reduce,.sort,.map或类似的人可以帮我解决这个问题?

4 个答案:

答案 0 :(得分:2)

(count 48)
=> 1
(count 4881)
=> 4
(count 8818)
=> 5

使用var locations = [1, 2, 3, 4, 5, 5, 5, 1, 2, 3, 4, 3, 3, 3] while !locations.isEmpty && locations.dropLast().last == locations.last { locations.removeLast() } print(locations) MapReduce不是必需的,实际上建议在这种情况下不要使用它们。因为一旦找到与上一个元素不同的元素,就应该停止阅读所有元素。

和@Eendje说:

  

其他答案也会删除除了以外的任何其他重复项   最后一个

OP使用的解决方案:

Filter

答案 1 :(得分:1)

首先,如果你有一个CLLocation数组,那么它可能看起来像这样

let locations: [CLLocation] = [
    CLLocation(latitude: 11.123, longitude: 11.123),
    CLLocation(latitude: 12.345, longitude: 123.123),
    CLLocation(latitude: 14.124, longitude: 14.124),
    CLLocation(latitude: 16.1661, longitude: 16.1616),
    CLLocation(latitude: 15.1515, longitude: 15.1515),
    CLLocation(latitude: 15.1515, longitude: 15.1515),
    CLLocation(latitude: 15.1515, longitude: 15.1515)]

现在我们可以像这样创建一个Set

var added = Set<CLLocation>()

最后过滤数组

let filtered = locations.filter { (location) -> Bool in
    let duplicate = added.contains { (location.coordinate.latitude, location.coordinate.longitude) == ($0.coordinate.latitude, $0.coordinate.longitude) }
    guard !duplicate else { return false }
    added.insert(location)
    return true
}

现在您的结果位于filtered

答案 2 :(得分:1)

要做到这一点,时间复杂度很高,您需要一个有序的数据结构实现。下面我将展示如何使用依赖the OrderedSet library的纯Swift解决方案来实现这一目标。

如果你不介意使用NSObject子类作为你的纬度&amp;经度对类型,您可以使用NSOrderedSet(array:…your location objects…).array执行此操作,其中…your location objects…指的是包含纬度和经度的NSObject子类。您需要向-hash课程实施-isEqual:Location。也就是说,下面示例代码中的原理非常相似:您需要一个包含纬度和范围的类型。经度对,可以清洗(在你的NSObject子类中覆盖-hash)和equatable(在你的NSObject中覆盖-isEqual:)。

import Darwin
import SortedSet

struct Location:Hashable {
    let lat:Double
    let long:Double

    var hashValue: Int {
        // This is a *terrible* hash function.
        // You'll find instructions from elsewhere for more performant ones. 
        return Int(ceil(lat + long))
    }
}

func ==(lhs: Location, rhs: Location) -> Bool {
    return lhs.lat == rhs.lat && lhs.long == rhs.long
}


let orderedLocations = OrderedSet<Location>(sequence: [Location(lat: 11.123, long: 11.123),
                                                        Location(lat: 12.345, long: 123.123),
                                                        Location(lat: 14.124, long: 14.124),
                                                        Location(lat: 16.1661, long: 16.1616),
                                                        Location(lat: 15.1515, long: 15.1515),
                                                        Location(lat: 15.1515, long: 15.1515),
                                                        Location(lat: 15.1515, long: 15.1515)])

for location in orderedLocations {
    print(location) // prints out the locations in the original order, with duplicates removed.
}

答案 3 :(得分:1)

let lastIndex = array.count - 1

if array[lastIndex] == array[lastIndex - 1] {
array.removeLast()
}
这样的事情会起作用。您可能需要调整它以满足您的特定需求。

*编辑 - 这些其他解决方案看起来更复杂,也许我误解了你的需求