swift 中的 index(where:) 方法生成了错误的索引
index(where:) method in swift is producing the wrong index
我收到数组索引超出范围错误。我有两个数组 cardsCurrentlyInPlay
和 currentCardsSelected
。这个游戏中的每张卡都有一个唯一的 ID。我试图在 cardsCurrentlyInPlay
中找到卡片的索引,其 cardID
与 currentCardsSelected
中卡片的 cardID
匹配。我通过使用需要闭包的 index(where:)
方法来做到这一点。我的闭包只是检查 ID 是否匹配,它们显然匹配,因为我正在使用 !
来解包它们并且应用程序不会在那里崩溃。 index(where:)
方法似乎返回了错误的索引。我已经看了好几个小时了,但我不明白发生了什么。
代码如下:
let indexOfFirstCard = cardsCurrentlyInPlay.index(where: ({([=11=]?.cardID == currentCardsSelected[0].cardID)}))!
let indexOfSecondCard = cardsCurrentlyInPlay.index(where: ({([=11=]?.cardID == currentCardsSelected[1].cardID)}))!
let indexOfThirdCard = cardsCurrentlyInPlay.index(where: ({([=11=]?.cardID == currentCardsSelected[2].cardID)}))!
if deck.isEmpty && selectedCardsMakeASet() {
/* Remove the old cards */
cardsCurrentlyInPlay.remove(at: indexOfFirstCard)
cardsCurrentlyInPlay.remove(at: indexOfSecondCard)
cardsCurrentlyInPlay.remove(at: indexOfThirdCard) // where code is blowing up
currentCardsSelected.removeAll()
/* Return indicies of cards to clear from the UI */
return .deckIsEmpty(indexOfFirstCard, indexOfSecondCard, indexOfThirdCard)
}
你得到的索引在你得到它时是正确的,但是当你移除其他卡片时它变得错误。考虑:
var a = ["x", "y", "z"]
let indexOfX = a.index(of: "x")! // returns 0
let indexOfZ = a.index(of: "z")! // returns 2
a.remove(at: indexOfX) // removes "x"; now a = ["y", "z"]
a.remove(at: indexOfZ) // index 2 is now out of bounds
您可以交替调用 index(of:)
和 remove(at:)
,但更好的方法是一次删除所有三张卡片,如下所示:
let selectedCardIDs = currentCardsSelected.map { [=11=].cardID }
cardsCurrentlyInPlay = cardsCurrentlyInPlay.filter { card in
!selectedCardIDs.contains(card.cardID)
}
请注意,这具有避免强制展开的额外好处,这是更合理逻辑的标志。
这是因为越界
前两段代码执行后。
cardsCurrentlyInPlay.remove(at: indexOfFirstCard)
&
cardsCurrentlyInPlay.remove(at: indexOfSecondCard)
cardsCurrentlyInPlay
中只有一个元素。
那么如果你执行cardsCurrentlyInPlay.remove(at: indexOfThirdCard)
,程序就会崩溃
我收到数组索引超出范围错误。我有两个数组 cardsCurrentlyInPlay
和 currentCardsSelected
。这个游戏中的每张卡都有一个唯一的 ID。我试图在 cardsCurrentlyInPlay
中找到卡片的索引,其 cardID
与 currentCardsSelected
中卡片的 cardID
匹配。我通过使用需要闭包的 index(where:)
方法来做到这一点。我的闭包只是检查 ID 是否匹配,它们显然匹配,因为我正在使用 !
来解包它们并且应用程序不会在那里崩溃。 index(where:)
方法似乎返回了错误的索引。我已经看了好几个小时了,但我不明白发生了什么。
代码如下:
let indexOfFirstCard = cardsCurrentlyInPlay.index(where: ({([=11=]?.cardID == currentCardsSelected[0].cardID)}))!
let indexOfSecondCard = cardsCurrentlyInPlay.index(where: ({([=11=]?.cardID == currentCardsSelected[1].cardID)}))!
let indexOfThirdCard = cardsCurrentlyInPlay.index(where: ({([=11=]?.cardID == currentCardsSelected[2].cardID)}))!
if deck.isEmpty && selectedCardsMakeASet() {
/* Remove the old cards */
cardsCurrentlyInPlay.remove(at: indexOfFirstCard)
cardsCurrentlyInPlay.remove(at: indexOfSecondCard)
cardsCurrentlyInPlay.remove(at: indexOfThirdCard) // where code is blowing up
currentCardsSelected.removeAll()
/* Return indicies of cards to clear from the UI */
return .deckIsEmpty(indexOfFirstCard, indexOfSecondCard, indexOfThirdCard)
}
你得到的索引在你得到它时是正确的,但是当你移除其他卡片时它变得错误。考虑:
var a = ["x", "y", "z"]
let indexOfX = a.index(of: "x")! // returns 0
let indexOfZ = a.index(of: "z")! // returns 2
a.remove(at: indexOfX) // removes "x"; now a = ["y", "z"]
a.remove(at: indexOfZ) // index 2 is now out of bounds
您可以交替调用 index(of:)
和 remove(at:)
,但更好的方法是一次删除所有三张卡片,如下所示:
let selectedCardIDs = currentCardsSelected.map { [=11=].cardID }
cardsCurrentlyInPlay = cardsCurrentlyInPlay.filter { card in
!selectedCardIDs.contains(card.cardID)
}
请注意,这具有避免强制展开的额外好处,这是更合理逻辑的标志。
这是因为越界
前两段代码执行后。
cardsCurrentlyInPlay.remove(at: indexOfFirstCard)
&
cardsCurrentlyInPlay.remove(at: indexOfSecondCard)
cardsCurrentlyInPlay
中只有一个元素。
那么如果你执行cardsCurrentlyInPlay.remove(at: indexOfThirdCard)
,程序就会崩溃