简体   繁体   English

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

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

I have an easy question that is also hard at the same time. 我有一个简单的问题,同时也很难解决。 I have two separate structs (this can also work for classes): 我有两个单独的结构(这也可以用于类):

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

and

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

I have an array of both structs var fbTweetArray: [FBTweet] = [] and var statusArray: [Status] = [] 我有两个结构的数组var fbTweetArray: [FBTweet] = []var statusArray: [Status] = []

I have set every variable in to a certain value in each index in fbTweetArray but I only set the .statusId variable in each index for statusArray. 我已经在fbTweetArray的每个索引中将每个变量设置为某个值,但是我仅在statusArray的每个索引中设置了.statusId变量。 For every statusArray.statusId value in statusArray, there is only one fbTweetArray.tweetId that has the same exact Int value. 对于statusArray.statusId中的每个statusArray.statusId值,只有一个fbTweetArray.tweetId具有完全相同的Int值。 I am trying to make is so that if these two variables are the same then I should set set statusArray.statusText to whatever fbTweetarray.tweetText is. 我想做的是,如果这两个变量相同,则应将statusArray.statusText设置为fbTweetarray.tweetText So for example only fbTweetArray[1].tweetid = 2346 and statusArray[4].statusId = 2346 have 2346 as their value. 因此,例如,仅fbTweetArray[1].tweetid = 2346statusArray[4].statusId = 2346的值为2346。 There for if fbTweetArray[1].tweetText = "hello friend" then statusArray[4].statusText needs to be set to "hello friend". 如果fbTweetArray[1].tweetText = "hello friend"那么statusArray[4].statusText需要设置为“ hello friend”。

So far I have 到目前为止,我有

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
            }
        }
    }
}

how do I set the for var status in the for loop back into the statusArray since it is now a var and is different than one of the indexes in var statusArray: [Status] = [] 我如何在for循环中将for var status设置回statusArray,因为它现在是var,并且与var statusArray: [Status] = []中的索引之一var statusArray: [Status] = []

Your question is interesting only if both the arrays are not ordered. 仅当两个数组均未排序时,您的问题才有意义。

To find the element from fbTweet array, you can sort it and employ binary search. 要从fbTweet数组中查找元素,可以对其进行排序并采用二进制搜索。 Then enumerate status array and find the fbTweet object with the same identifier and modify the status object. 然后枚举状态数组,找到具有相同标识符的fbTweet对象,然后修改状态对象。 It needs to be saved again in the array as structs get copied on write. 当结构在写入时被复制时,需要再次将其保存在数组中。

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
}

Basically, you need only one for / forEach loop to achieve what you want: 基本上,您只需要一个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")]

Note, that your id s in both structures can be nil . 请注意,两个结构中的id都可以为nil To handle this situation (if both id is nil - objects are not equal) you can write custom == func: 要处理这种情况(如果两个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 }) { ... }

Also, there is some pro-tip. 另外,还有一些提示。 If you adopt your structs to Hashable protocol, you will be able to place FBTweet s and Status es into Set structure. 如果将结构采用Hashable协议,则可以将FBTweetStatus放入Set结构中。 The benefits of that: 这样做的好处:

If you instead store those objects in a set, you can theoretically find any one of them in constant time (O(1)) — that is, a lookup on a set with 10 elements takes the same amount of time as a lookup on a set with 10,000. 如果改为将这些对象存储在集合中,则理论上可以在恒定时间内(O(1))找到它们中的任何一个,也就是说,在具有10个元素的集合中进行查找所花费的时间与在对象上进行查找所花费的时间相同。设置为10,000。

You can find more in-depth info about it in a new great article by NSHipster . 您可以在NSHipster撰写的新文章中找到有关它的更多详细信息。

An alternative would be use dictionaries instead of arrays, for better performance and easier implementation (in this case). 一种替代方法是使用字典而不是数组,以提高性能并简化实现(在这种情况下)。 You can easily get the array of keys and values later If you need. 如果需要,以后可以轻松获取键和值的数组。

In this case, the Id would be the Key of the dictionary, and the text the value. 在这种情况下,Id将是字典的键,文本将是值。

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

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