source

Swift에서 열거하는 동안 배열에서 제거하시겠습니까?

factcode 2023. 9. 11. 22:16
반응형

Swift에서 열거하는 동안 배열에서 제거하시겠습니까?

스위프트에서 배열을 통해 열거하고, 특정 항목을 제거하고 싶습니다.저는 이것이 안전한지, 안전하지 않다면 이것을 어떻게 달성해야 하는지 궁금합니다.

지금은 이렇게 할 겁니다

for (index, aString: String) in enumerate(array) {
    //Some of the strings...
    array.removeAtIndex(index)
}

스위프트 2에서는 사용하기가 아주 쉽습니다.enumerate그리고.reverse.

var a = [1,2,3,4,5,6]
for (i,num) in a.enumerate().reverse() {
    a.removeAtIndex(i)
}
print(a)

생각해 보셔도 좋습니다.filter방법:

var theStrings = ["foo", "bar", "zxy"]

// Filter only strings that begins with "b"
theStrings = theStrings.filter { $0.hasPrefix("b") }

매개변수는filter이 경우 배열 유형 인스턴스를 수행하는 클로저일 뿐입니다.String) 및 a를 반환합니다.Bool. 결과가 다음일 때true요소를 유지합니다. 그렇지 않으면 요소가 걸러집니다.

Swift 3 및 4에서 다음과 같은 것을 의미합니다.

존스턴의 대답에 따르면 숫자와 함께:

var a = [1,2,3,4,5,6]
for (i,num) in a.enumerated().reversed() {
   a.remove(at: i)
}
print(a)

OP의 질문으로 문자열을 사용합니다.

var b = ["a", "b", "c", "d", "e", "f"]

for (i,str) in b.enumerated().reversed()
{
    if str == "c"
    {
        b.remove(at: i)
    }
}
print(b)

그러나 현재 Swift 4.2 이상 버전에서는 Apple이 WWDC2018에서 추천한 더 좋고 빠른 방법이 있습니다.

var c = ["a", "b", "c", "d", "e", "f"]
c.removeAll(where: {$0 == "c"})
print(c)

이 새로운 방식에는 다음과 같은 몇 가지 장점이 있습니다.

  1. 를 통해 구현하는 것보다 빠릅니다.filter.
  2. 어레이를 반대로 돌릴 필요가 없습니다.
  3. 제자리에 있는 항목을 제거하므로 새 배열을 할당하고 반환하는 대신 원래 배열을 업데이트합니다.

배열에서 특정 인덱스의 요소를 제거하면 한 위치만큼 뒤로 이동하기 때문에 이후의 모든 요소의 위치(및 인덱스)가 변경됩니다.

따라서 가장 좋은 방법은 배열을 역순으로 탐색하는 것입니다. 이 경우 기존의 for loop을 사용하는 것이 좋습니다.

for var index = array.count - 1; index >= 0; --index {
    if condition {
        array.removeAtIndex(index)
    }
}

하지만 내 생각에 가장 좋은 접근법은filter@perfly가 그의 답변에서 설명한 방법.

아니요, 열거하는 동안 배열을 변형하는 것은 안전하지 않습니다. 코드가 충돌하게 됩니다.

개체를 몇 개만 삭제하려면filter기능.

삭제할 항목을 저장할 가변 배열을 만든 다음 열거가 끝나면 해당 항목을 원본에서 제거합니다.또는 배열의 복사본(불변)을 만들고, 이를 열거하고, 열거하는 동안 원래에서 개체(인덱스 기준이 아닌)를 제거합니다.

기존의 for loop은 단순한 while loop으로 대체할 수 있습니다. 제거하기 전에 각 요소에 대해 다른 작업을 수행해야 하는 경우에도 유용합니다.

var index = array.count-1
while index >= 0 {

     let element = array[index]
     //any operations on element
     array.remove(at: index)

     index -= 1
}

열거하는 동안 요소를 0으로 설정하고, 완료한 후 배열 필터() 방법을 사용하여 빈 요소를 모두 제거하는 것을 권장합니다.

덧붙이자면, 배열 A의 인덱스 N에 있는 각 요소가 배열 B의 인덱스 N과 연관되어 있다면, (과거의 답처럼) 열거된 배열을 뒤집는 방법을 사용할 수 있습니다.그러나 다른 어레이의 요소에 액세스하고 삭제할 때는 이 요소를 되돌릴 필요가 없습니다.

Like so, (one can copy and paste this on Playground)

var a = ["a", "b", "c", "d"]
var b = [1, 2, 3, 4]
var c = ["!", "@", "#", "$"]

// remove c, 3, #

for (index, ch) in a.enumerated().reversed() {
    print("CH: \(ch). INDEX: \(index) | b: \(b[index]) | c: \(c[index])")
    if ch == "c" {
        a.remove(at: index)
        b.remove(at: index)
        c.remove(at: index)
    }
}

print("-----")
print(a) // ["a", "b", "d"]
print(b) // [1, 2, 4]
print(c) // ["!", "@", "$"]

언급URL : https://stackoverflow.com/questions/28323848/removing-from-array-during-enumeration-in-swift

반응형