Swift 3의 배열에서 객체 제거


94

내 응용 프로그램에서 셀을 선택할 때 배열에 하나의 개체를 추가하고 셀을 다시 선택할 때 개체를 선택 취소하고 제거했습니다. 그 코드를 사용했지만 오류가 발생했습니다.

extension Array {
    func indexOfObject(object : AnyObject) -> NSInteger {
        return (self as NSArray).indexOfObject(object)
    }

    mutating func removeObject(object : AnyObject) {
        for var index = self.indexOfObject(object); index != NSNotFound; index = self.indexOfObject(object) {
            self.removeAtIndex(index)
        }
    }
}

class MyViewController: UITableViewController {
    var arrContacts: [Any] = []
    var contacts: [Any] = []

    func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
        arrContacts.removeObject(contacts[indexPath.row])
    }
}

다음과 같은 2 개의 오류가 발생합니다.

C-style for statement has been removed in Swift 3
Value of type '[Any]' has no member 'removeObject'

Set<Contact>대신 배열을 사용할 수 있습니다 . 연락처 개체에 대한 추가 정보를 제공 할 수 있습니까? 당신이 스스로 한 경우 당신은 준수해야합니다 HashableEquatable세트에 넣어하기 위해
Paulw11

답변:


168

에 대한 스위프트 동등한 NSMutableArray'들 removeObject입니다 :

var array = ["alpha", "beta", "gamma"]

if let index = array.firstIndex(of: "beta") {
    array.remove(at: index)
}

개체가 고유 한 경우 . 캐스팅 NSArray하고 사용할 필요가 전혀 없습니다.indexOfObject:

API index(of:도 작동하지만 이로 인해 불필요한 암시 적 브리지가 NSArray.

동일한 개체가 여러 번 발생하는 경우 filter. 그러나 인덱스가 특정 개체와 연결된 데이터 소스의 배열과 같은 경우에 firstIndex(of이보다 더 빨리 때문에 바람직하다 filter.

최신 정보:

Swift 4.2 이상에서는 betawith를 하나 또는 여러 번 제거 할 수 있습니다 removeAll(where:).

array.removeAll{$0 == "beta"}

35
이것이 최선의 대답이지만 remove (object : "beta")가없는 것은 어리석은 일이 아닙니다.
zeeple

5
.index(of: 컬렉션에 Equatable유형이 포함 된 경우에만 사용할 수 있다고 생각 합니다.
Adam Waite

@AdamWaite 예, 그러나 이것은 재단 유형에도 적용됩니다.
vadian

이것은 옳지 않습니다. 만약 당신이 하나 이상의 "베타"를 가지고 있다면? 이것은 배열에 둘 이상의 발생이 포함되지 않은 경우에만 작동합니다. 정답은 필터를 사용하거나 잠시 while let index = array.index(of: "beta") { array.remove(at: index) }
후에이

@juancazalla 당신이 맞지만 배열에 둘 이상의 발생이 포함될 수있는 경우 filter솔루션을 사용하십시오 . 그러나 객체가 고유 한 경우 항상 index(of성능이 훨씬 더 높기 때문에 항상 사용합니다filter
vadian

72
var a = ["one", "two", "three", "four", "five"]

// Remove/filter item with value 'three'
a = a.filter { $0 != "three" }

7
이것이 언어가 제공하는 구문을 활용하는 올바른 Swift 솔루션입니다.
Michael

1
항목이 개체이면 어떻게 되나요?
TomSawyer

객체 필터링 @TomSawyer은 $ 0 사용 ==!
마이크 Taverne 당시

25

Swift 3의 경우 index (where :)를 사용하고 배열 ($ 0)의 객체를 찾고있는 객체와 비교하는 클로저를 포함 할 수 있습니다.

var array = ["alpha", "beta", "gamma"]
if let index = array.index(where: {$0 == "beta"}) {
  array.remove(at: index)
}

여러 개체를 제거하려면이 기능이 작동합니까? like (where : {$ 0 == "beta"|| $ 0 == "gamma"})
Irshad Mohamed

16

또 다른 훌륭하고 유용한 솔루션은 이러한 종류의 확장을 만드는 것입니다.

extension Array where Element: Equatable {

    @discardableResult mutating func remove(object: Element) -> Bool {
        if let index = index(of: object) {
            self.remove(at: index)
            return true
        }
        return false
    }

    @discardableResult mutating func remove(where predicate: (Array.Iterator.Element) -> Bool) -> Bool {
        if let index = self.index(where: { (element) -> Bool in
            return predicate(element)
        }) {
            self.remove(at: index)
            return true
        }
        return false
    }

}

이런 식으로 사용자 지정 개체가있는 배열이있는 경우 :

let obj1 = MyObject(id: 1)
let obj2 = MyObject(id: 2)
var array: [MyObject] = [obj1, obj2]

array.remove(where: { (obj) -> Bool in
    return obj.id == 1
})
// OR
array.remove(object: obj2) 

1
이것은 배열에 둘 이상의 발생이 포함되지 않은 경우에만 작동합니다. 정답은 필터를 사용하거나 잠시 동안이 답변을 실행하는 것입니다. 이 확장의 사용자로서, 나는 모든 사건이 아니라 하나의 제거를 기대
juancazalla

좋지만 remove(element: Element)Array에 Int, Double과 같은 유형도 저장할 수 있기 때문에 그럴 것 입니다. 객체가 아닙니다.
Radek Wilczak

8

에서 스위프트 (5) ,이 옵션을 사용합니다 Extension:

extension Array where Element: Equatable{
    mutating func remove (element: Element) {
        if let i = self.firstIndex(of: element) {
            self.remove(at: i)
        }
    }
}

예:

var array = ["alpha", "beta", "gamma"]
array.remove(element: "beta")

에서 스위프트 3 ,이 옵션을 사용합니다 Extension:

extension Array where Element: Equatable{
    mutating func remove (element: Element) {
        if let i = self.index(of: element) {
            self.remove(at: i)
        }
    }
}

예:

var array = ["alpha", "beta", "gamma"]
array.remove(element: "beta")

6
  1. for var index = self.indexOfObject(object); index != NSNotFound; index = self.indexOfObject(object) C 스타일의 for 루프이며 제거되었습니다.

  2. 루프가 발생한 경우 유사한 객체를 모두 제거하려면 코드를 다음과 같이 변경하십시오.

    let indexes = arrContacts.enumerated().filter { $0.element == contacts[indexPath.row] }.map{ $0.offset }
    for index in indexes.reversed() {
       arrContacts.remove(at: index)
    }
    

열거-> 필터->지도 및 제거 (at)가 스마트 솔루션입니다. 이 하나 추천
라이언 X

4

스위프트 4

var students = ["Kofi", "Abena", "Peter", "Kweku", "Akosua"]

if let index = students.firstIndex(where: { $0.hasPrefix("A") }) {
   students.remove(at: index)
}

3

Swift 3에서 이러한 객체 배열 ( "array"라고 함)에서 고유 한 객체 ( "objectToRemove"라고 함)를 삭제하는 정확하고 작동하는 한 줄 솔루션은 다음과 같습니다.

if let index = array.enumerated().filter( { $0.element === objectToRemove }).map({ $0.offset }).first {
   array.remove(at: index)
}

1

Swift 3에서 시도해보세요

array.remove(at: Index)

대신에

array.removeAtIndex(index)

최신 정보

"Declaration is only valid at file scope".

개체가 범위 내에 있는지 확인하십시오. 기본값 인 "내부"범위를 지정할 수 있습니다.

index(of:<Object>) 일하려면 수업은 Equatable


1

에서는 스위프트 (3, 4)

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

for (index, element) in array.enumerated().reversed() {
    array.remove(at: index)
}

Swift 4.2 부터는 보다 진보 된 접근 방식을 사용할 수 있습니다 (더 빠르고 메모리 효율적).

array.removeAll(where: { $0 == "c" })

대신에

array = array.filter { !$0.hasPrefix("c") }

여기에서 더 많은 것을 읽으 십시오


1

배열을 쉽게 수행하고 Swift 4.2 이상에 대한 연결을 허용하는 확장 :

public extension Array where Element: Equatable {
    @discardableResult
    public mutating func remove(_ item: Element) -> Array {
        if let index = firstIndex(where: { item == $0 }) {
            remove(at: index)
        }
        return self
    }

    @discardableResult
    public mutating func removeAll(_ item: Element) -> Array {
        removeAll(where: { item == $0 })
        return self
    }
}

인수 레이블 '(where :)'가 사용 가능한 오버로드와 일치하지 않습니다
jeet.chanchawat

1
@ jeet.chanchawat 그럼 아마 다른 신속한 버전이 될 것입니다 ... 오이 질문은 3입니까? 글을 쓰는 시점에 4.2가 있었지만 지금은 기억 나지 않습니다. 나중에 확인할 것입니다. 확실히 저에게
효과적


0

이것이 제가 사용한 것입니다 (Swift 5) ...

    extension Array where Element:Equatable
    {
        @discardableResult
        mutating func removeFirst(_ item:Any ) -> Any? {
            for index in 0..<self.count {
                if(item as? Element == self[index]) {
                    return self.remove(at: index)
                }
            }
            return nil
        }
        @discardableResult
        mutating func removeLast(_ item:Any ) -> Any? {
            var index = self.count-1
            while index >= 0 {
                if(item as? Element == self[index]) {
                    return self.remove(at: index)
                }
                index -= 1
            }
            return nil
        }
    }

    var arrContacts:[String] = ["A","B","D","C","B","D"]
    var contacts: [Any] = ["B","D"]
    print(arrContacts)
    var index = 1
    arrContacts.removeFirst(contacts[index])
    print(arrContacts)
    index = 0
    arrContacts.removeLast(contacts[index])
    print(arrContacts)

결과 :

   ["A", "B", "D", "C", "B", "D"]
   ["A", "B", "C", "B", "D"]
   ["A", "B", "C", "D"]

중요 : 항목을 제거하는 배열에는 Equatable 요소 (예 : 객체, 문자열, 숫자 등)가 포함되어야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.