[英]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 = 2346
和statusArray[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
协议,则可以将FBTweet
和Status
放入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.