我有一个对象数组
var arrayOfObjects: [Object]?
他们都有一个叫depth
的属性。我想在该数组中找到与特定对象具有相同深度的非常下一个对象,我知道索引为:
[
...objects_before...,
object_I_know: {depth:3},
...objects_after...
]
除了使用从object_I_know
索引开始的for循环以及向下遍历直到找到它之外,是否有更有效的方法?
答案 0 :(得分:3)
let nextIndex: Int? = (givenIndex ..< array.endIndex).first { index in
return array[index].depth == array[givenIndex].depth
}
如果有一个
,具有相同深度的对象的项目将位于该nextIndex
let nextObject: Object? = (nextIndex == nil) ? nil : array[nextIndex!]
答案 1 :(得分:0)
class Object {
var name: String
var depth: Float
init(name: String, depth: Float) {
self.name = name
self.depth = depth
}
}
let o1 = Object(name: "object1", depth: 10)
let o2 = Object(name: "object2", depth: 12)
let o3 = Object(name: "object3", depth: 4)
let o4 = Object(name: "object4", depth: 12)
let o5 = Object(name: "object5", depth: 14)
let array = [o1, o2, o3, o4, o5]
let knownIndex = 1
let knownDepth = array[knownIndex].depth
var searchResults = [Object]()
// iterate through the second half of the array after the known
// index and break the loop when a match is found
for i in knownIndex + 1..<array.count {
if array[i].depth == knownDepth {
searchResults = [array[i]]
break
}
}
// after the loop is finished (either by going all the way to the
// end or breaking after a match is found), check your search results
if searchResults.count > 0 {
print("match found: \(searchResults[0].name)")
} else {
print("no match found")
}
index(where:)
也使用了一个循环,这是评论者不知道的,除了编译器在幕后为你做。 index(where:)
也循环遍历整个数组,如果你已经知道起始索引(OP确实如此),那么效率不高。
答案 2 :(得分:0)
这是我提出的用于测试的示例模型:
struct S {
let id: Int
let depth: Int
}
var id = 0
let getID: () -> Int = { defer { id += 1 }; return id }
let objects = [
S(id: getID(), depth: 1),
S(id: getID(), depth: 3),
S(id: getID(), depth: 2),
S(id: getID(), depth: 3),
S(id: getID(), depth: 4),
]
这是一个解决方案,它解释了没有与谓词匹配的元素的情况,或只有1个这样的元素:
let isDepth3: (S) -> Bool = { $0.depth == 3 }
// Get the index of the first item (can be nil)
let indexOfFirstDepth3 = objects.index(where: isDepth3)
// Get the index after that (can be nil), so that we can exclude everything before it
let firstIndexOfRemainingItems = indexOfFirstDepth3.flatMap { objects.index($0, offsetBy: +1, limitedBy: objects.endIndex) }
let indexOfSecondDepth3 = firstIndexOfRemainingItems.flatMap {
// Slice the `objects` array, to omit all the items before up to and including the first depth 3 item.
// Then find the index of the next next 3 item thereafter.
return objects[$0...].index(where: isDepth3)
}
// Print results
func stringifyOptional<T>(_ item: T?) -> String {
return item.map{ String(describing: $0) } ?? "nil"
}
print("First item with depth 3 is \(stringifyOptional(indexOfFirstDepth3.map{ objects[$0] })) at index \(stringifyOptional(indexOfFirstDepth3))")
print("Second item with depth 3 is \(stringifyOptional(indexOfSecondDepth3.map{ objects[$0] })) at index \(stringifyOptional(indexOfFirstDepth3))")
如果你 确定 你将拥有2个这样的元素,并且你确定强行展开是安全的,那么这可以大大简化:
let isDepth3: (S) -> Bool = { $0.depth == 3 }
let indexOfFirstDepth3 = objects.index(where: isDepth3)!
let indexOfSecondDepth3 = objects[indexOfFirstDepth3...].index(where: isDepth3)!
// Just printing the result
print("First item with depth 3 is \(objects[indexOfFirstDepth3]) at index \(indexOfFirstDepth3)")
print("Second item with depth 3 is \(objects[indexOfFirstDepth3])) at index \(indexOfFirstDepth3)")
答案 3 :(得分:0)
<强>上下文强>
struct DepthObject { let depth: Int }
let objs = [a, b, c, d ,e]
let index = 1 //predetermined index
let depthToFind = objs[index].depth
let startIndex = index + 1
let remainingArray = objs[startIndex...] //The slice we want to work with
单程
let aMessage: String? = remainingArray
.first { $0.depth == depthToFind }
.flatMap { "The world is yours \($0)" }
根据它决定
if let nextDepthObject = remainingArray.first(where: { $0.depth == depthToFind }) {
//Found the next one!
} else {
//Didn't find it!
}
循环播放
var nextDepthObject: DepthObject? = nil
for sliceDepthObject in remainingArray {
if sliceDepthObject.depth == depthToFind {
nextDepthObject = sliceDepthObject
break
}
}
实施特定方法
func nextDepthObject(within array: Array<DepthObject>, startingAt index: Int) -> DepthObject? {
guard index + 1 < array.count && index < array.count else {
return nil
}
let depthToFind = array[index].depth
let suffixArray = array[(index + 1)...]
return suffixArray.first { $0.depth == depthToFind }
}
let theNextOne: DepthObject? = nextDepthObject(within: objs, startingAt: index)
答案 4 :(得分:0)
您可以在Collection
(Array
符合)上添加扩展程序:
extension Collection {
func next(startingWith next: Self.Index, where match: (Element) -> Bool) -> Element? {
guard next < endIndex else { return nil }
return self[next..<endIndex].first(where: match)
}
}
你会这样使用它:
let nextMatch = arrayOfObjects.next(startingWith: foundIndex+1) { $0.depth == searchedDepth }