代码之家  ›  专栏  ›  技术社区  ›  Ben Akin

迭代两个自定义数组,如果变量相等,则设置值

  •  0
  • Ben Akin  · 技术社区  · 6 年前

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

    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中每个索引中的每个变量设置为特定值,但我只设置 .statusId statusArray的每个索引中的变量。为每一个 statusArray.statusId 值在statusArray中,只有一个 fbTweetArray.tweetId 具有相同的精确Int值。我想做的是,如果这两个变量相同,我应该设置 statusArray.statusText 不管怎样 fbTweetarray.tweetText 是。例如 fbTweetArray[1].tweetid = 2346 statusArray[4].statusId = 2346 价值2346英镑。在那里如果 fbTweetArray[1].tweetText = "hello friend" statusArray[4].statusText 需要设置为“你好朋友”。

    到目前为止

    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 var status 在for循环中返回到statusArray,因为它现在是一个var,并且不同于 var statusArray:[状态]=[]

    3 回复  |  直到 6 年前
        1
  •  1
  •   pacification    6 年前

    基本上,你只需要一个 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-对象不相等),可以编写自定义 ==

    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 协议,你可以 FBTweet s和 Status Set 结构。这样做的好处是:

    在恒定时间(O(1))中查找其中任何一个,即查找 设置为10个元素所需的时间与查找

    你可以在一个新的伟大的 article by NSHipster .

        2
  •  1
  •   Puneet Sharma    6 年前

    只有当两个数组都没有排序时,您的问题才有趣。

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

    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
    }
    
        3
  •  0
  •   jXavier    6 年前

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