繁体   English   中英

遍历两个自定义数组并在变量相等时设置值Swift

[英]iterate through two custom arrays and set values if variables are equal Swift

我有一个简单的问题,同时也很难解决。 我有两个单独的结构(这也可以用于类):

struct FBTweet {
    var tweetId: Int? //set
    var tweetText: String?  //set
}

struct Status {
    var statusId: Int? //set
    var statusText: String? //no value
    }

我有两个结构的数组var fbTweetArray: [FBTweet] = []var statusArray: [Status] = []

我已经在fbTweetArray的每个索引中将每个变量设置为某个值,但是我仅在statusArray的每个索引中设置了.statusId变量。 对于statusArray.statusId中的每个statusArray.statusId值,只有一个fbTweetArray.tweetId具有完全相同的Int值。 我想做的是,如果这两个变量相同,则应将statusArray.statusText设置为fbTweetarray.tweetText 因此,例如,仅fbTweetArray[1].tweetid = 2346statusArray[4].statusId = 2346的值为2346。 如果fbTweetArray[1].tweetText = "hello friend"那么statusArray[4].statusText需要设置为“ hello friend”。

到目前为止,我有

func testWhat () {

    var fbTweetArray: [FBTweet] = []
    var statusArray: [Status] = []

    for  fbTweet in fbTweetArray {
        for var status in statusArray {
            if (status.statusId == fbTweet.tweetId ) {
                status.statusText = fbTweet.tweetText
            }
        }
    }
}

我如何在for循环中将for var status设置回statusArray,因为它现在是var,并且与var statusArray: [Status] = []中的索引之一var statusArray: [Status] = []

仅当两个数组均未排序时,您的问题才有意义。

要从fbTweet数组中查找元素,可以对其进行排序并采用二进制搜索。 然后枚举状态数组,找到具有相同标识符的fbTweet对象,然后修改状态对象。 当结构在写入时被复制时,需要再次将其保存在数组中。

extension Array where Element == FBTweet {
    func binarySearchFBTweetWith(_ id:Int) -> FBTweet? {
        var range = 0..<self.count
        while range.startIndex < range.endIndex {
            let midIndex = range.startIndex + (range.endIndex - range.startIndex) / 2
            guard let tweetId = self[midIndex].tweetId else {
                continue
            }
            if tweetId == id {
                return self[midIndex]
            } else if tweetId < id {
                range = midIndex+1..<range.endIndex
            } else {
                range = range.startIndex..<midIndex
            }
        }
        return nil
    }
}

fbTweetArray.sort{($0.tweetId ?? 0) < ($1.tweetId ?? 0)}
for (index, status) in statusArray.enumerated() {
    guard let statusId = status.statusId else {continue}
    guard let fbTweet = fbTweetArray.binarySearchFBTweetWith(statusId) else {continue}
    var status = status
    status.statusText = fbTweet.tweetText
    statusArray[index] = status
}

基本上,您只需要一个for / forEach循环即可实现所需的功能:

var fbTweetArray: [FBTweet] = [
    FBTweet(tweetId: 1, tweetText: "1"),
    FBTweet(tweetId: 2, tweetText: "2"),
    FBTweet(tweetId: 3, tweetText: "3")
]

var statusArray: [Status] = [
    Status(statusId: 2, statusText: nil),
    Status(statusId: 1, statusText: nil),
    Status(statusId: 3, statusText: nil)
]

fbTweetArray.forEach { tweet in
    if let index = statusArray.index(where: { $0.statusId == tweet.tweetId }) {
        statusArray[index].statusText = tweet.tweetText
    }
}

print(statusArray.map { $0.statusText }) // [Optional("2"), Optional("1"), Optional("3")]

请注意,两个结构中的id都可以为nil 要处理这种情况(如果两个id均为nil-对象不相等),则可以编写custom == func:

struct Status {
    var statusId: Int? //set
    var statusText: String? //no value

    static func == (lhs: Status, rhs: FBTweet) -> Bool {
        guard let lhsId = lhs.statusId, let rhsId = rhs.tweetId else { return false }
        return lhsId == rhsId
    }
}

...

// rewrite .index(where: ) in if condition
if let index = statusArray.index(where: { $0 == tweet }) { ... }

另外,还有一些提示。 如果将结构采用Hashable协议,则可以将FBTweetStatus放入Set结构中。 这样做的好处:

如果改为将这些对象存储在集合中,则理论上可以在恒定时间内(O(1))找到它们中的任何一个,也就是说,在具有10个元素的集合中进行查找所花费的时间与在对象上进行查找所花费的时间相同。设置为10,000。

您可以在NSHipster撰写的新文章中找到有关它的更多详细信息。

一种替代方法是使用字典而不是数组,以提高性能并简化实现(在这种情况下)。 如果需要,以后可以轻松获取键和值的数组。

在这种情况下,Id将是字典的键,文本将是值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM