Ios 根据唯一属性id快速添加或更新项目数组

Ios 根据唯一属性id快速添加或更新项目数组,ios,arrays,swift,Ios,Arrays,Swift,我正在寻找有效的算法,可以将对象数组(对象是类而不是结构)添加到现有数组中。要求是,如果现有数组包含id相同的对象,函数将更新该对象(根据更新的对象更改现有对象的属性)。如果现有数组中不包括object.id,则函数只需将该对象添加到现有数组中即可。返回数组由新对象和更新对象组成 如果object.id是新的,则基本上只添加对象。如果已经包含object.id,它将更新对象的属性 我在下面试过了 func addPhotoArray(_ photos: [Photo], addedPhoto:

我正在寻找有效的算法,可以将对象数组(对象是类而不是结构)添加到现有数组中。要求是,如果现有数组包含id相同的对象,函数将更新该对象(根据更新的对象更改现有对象的属性)。如果现有数组中不包括
object.id
,则函数只需将该对象添加到现有数组中即可。返回数组由新对象和更新对象组成

如果object.id是新的,则基本上只添加对象。如果已经包含object.id,它将更新对象的属性

我在下面试过了

func addPhotoArray(_ photos: [Photo], addedPhoto: [Photo]) -> [Photo]{
        var resultArray = photos
        let originalIds = photos.map{$0.id}

        for photo in addedPhoto {
            if !originalIds.contains(photo.id) {
                resultArray.append(photo)
            }
        }
        return resultArray
    }
但我缺少更新要求。我怎样才能解决这个问题

更新 用索引替换项是一个选项。但是,如果只有1个或2个属性发生了更改,或者根本没有任何更改,则不确定它是否有效。我也在考虑使用
集合
。如何符合hashable,我们可以使用union函数,如下所示

extension Photo {
    static func union (left: [Photo],right: [Photo] ) -> [Photo]{
        return Array(Set(left).union(Set(right)))
    }

    static func ==(lhs: Photo, rhs: Photo) -> Bool {
        return lhs.id == rhs.id
    }
}

类型为
[YourIdType:YourObjectType]
的字典是您的解决方案。插入和检索成本为
O(1)
。在您的情况下,最坏的情况复杂性将是
O(n)
,其中
n=addedArray.count


更多关于类型的字典
[YourIdType:YourObjectType]
是您的解决方案。插入和检索成本为
O(1)
。在您的情况下,最坏的情况复杂性将是
O(n)
,其中
n=addedArray.count

有关

的更多信息,您可以尝试以下方法:

func addPhotoArray(_ photos: [Photo], addedPhoto: [Photo]) -> [Photo]{
    var resultArray = photos
    for photo in addedPhoto {
        // Search for the object is it already exists
        if let existingPhotoIndex = photos.firstIndex(where: { (tempPhoto) -> Bool in
                return photo.id == tempPhoto.id
            }) {
             resultArray[existingPhotoIndex] = photo // Replace the object 
        }
        else {
            resultArray.append(photo) // Insert new Object
        }
    }
    return resultArray
}
如果需要,您可以进一步改进。

您可以尝试以下方法:

func addPhotoArray(_ photos: [Photo], addedPhoto: [Photo]) -> [Photo]{
    var resultArray = photos
    for photo in addedPhoto {
        // Search for the object is it already exists
        if let existingPhotoIndex = photos.firstIndex(where: { (tempPhoto) -> Bool in
                return photo.id == tempPhoto.id
            }) {
             resultArray[existingPhotoIndex] = photo // Replace the object 
        }
        else {
            resultArray.append(photo) // Insert new Object
        }
    }
    return resultArray
}

如果您愿意,您可以进一步改进此功能。

我选择不使用id数组,而是使用
firstIndex
查找重复的照片(我假设原始数组中的所有照片都是唯一的),如果找到一张,我将其替换为新版本

func addPhotoArray(_ photos: [Photo], addedPhoto: [Photo]) -> [Photo]{
    var resultArray = photos

    for photo in addedPhoto {
        if let photoIndex = resultArray.firstIndex(where: { $0.id == photo.id}) {
            resultArray[photoIndex] = photo
        } else {
            resultArray.append(photo)
        }
    }
    return resultArray
}

我选择不使用id数组,而是使用
firstIndex
查找重复的照片(我假设原始数组中的所有照片都是唯一的),如果找到了一张,我会将其替换为新版本

func addPhotoArray(_ photos: [Photo], addedPhoto: [Photo]) -> [Photo]{
    var resultArray = photos

    for photo in addedPhoto {
        if let photoIndex = resultArray.firstIndex(where: { $0.id == photo.id}) {
            resultArray[photoIndex] = photo
        } else {
            resultArray.append(photo)
        }
    }
    return resultArray
}


你为什么不使用一本以
photo.id
为关键的字典呢?我看了你的最新消息后认为这会更符合你的目的,如果您想要使用Hashable的解决方案,您应该问一个新问题,但在我看来,您将有一个完全替换对象的解决方案。谢谢您的意思是使用Set,我们最终也将替换现有项?为什么不使用以
photo.id
为关键的字典?在我看来,这会更好地满足您的目的。在我看来,查看您的更新,如果您想要使用Hashable的解决方案,您应该问一个新问题,但在我看来,您将有一个完全替换对象的解决方案。谢谢您的意思是使用Set,我们最终也将替换现有项?这包含逻辑错误和编译错误,
photos[existingPhotoIndex]=photo
替换选项是否有效?假设我有一个更新func,比如mutating func updatePhoto(photo:photo,updatedPhoto:photo)。我们如何更新而不是替换?(当只有1.2属性更改或根本没有更改。更新似乎更好吗?)这包含逻辑错误和编译错误,
photos[existingPhotoIndex]=photo
替换选项是否有效?假设我有一个更新func,比如mutating func updatePhoto(photo:photo,updatedPhoto:photo)。我们如何更新而不是替换?(当只有1.2属性更改或根本没有更改时。更新似乎更好?)谢谢。替换为索引是一种选择,但如果只有1.2属性是更改的,那么它是否有效?我还要补充一个问题,我们如何实现SetTrue,但这不是你问题的一部分,所以我不知道如何实现。您可以先使用
(其中:)
获取现有对象而不是索引,然后使用某个自定义合并函数更新它。我们如何在没有完全替换的情况下进行更新?没有自动的方法可以做到这一点,您必须逐个属性检查是否有更改,并可能对其进行更新。而且我不会把这样一个方法变成类方法,所以接口应该是`updatePhoto(uUpdatedPhoto:Photo),谢谢我已经更改了func签名,但是我们把这个函数放在哪里呢?我们仅更改该项目,但不更改ResultaryThank中的项目。替换为索引是一种选择,但如果只有1.2属性是更改的,那么它是否有效?我还要补充一个问题,我们如何实现SetTrue,但这不是你问题的一部分,所以我不知道如何实现。您可以先使用
(其中:)
获取现有对象而不是索引,然后使用某个自定义合并函数更新它。我们如何在没有完全替换的情况下进行更新?没有自动的方法可以做到这一点,您必须逐个属性检查是否有更改,并可能对其进行更新。而且我不会把这样一个方法变成类方法,所以接口应该是`updatePhoto(uUpdatedPhoto:Photo),谢谢我已经更改了func签名,但是我们把这个函数放在哪里呢?我们只更改该项,但不更改Resultarray中的项。您有如何实现字典的示例吗?为您创建了一个示例。把它粘贴到游乐场,看看它是如何工作的。更新你的答案,阅读评论部分的代码几乎是不可能的。我正在尝试阅读你在pasterbin中的建议。但似乎我们最终还是替换了对象,而不是更新它?正如您所提到的,您的对象是引用类型,所以它没有问题。一般来说,我建议您限制过早优化。在分析和确定代码的瓶颈之后,优化是必要的。你有一个例子吗