programing

값을 기준으로 개체를 제거할 어레이 확장

telebox 2023. 4. 12. 22:13
반응형

값을 기준으로 개체를 제거할 어레이 확장

extension Array {
    func removeObject<T where T : Equatable>(object: T) {
        var index = find(self, object)
        self.removeAtIndex(index)
    }
}

요.var index = find(self, object)

'T'는 'T'로 변환할 수 없습니다.

시그니처도 .func removeObject(object: AnyObject)오류인 '있다', '어느 정도 있다'가 나옵니다

'AnyObject'는 'T'로 변환할 수 없습니다.

어떻게 하면 좋을까요?

Swift 2에서는 프로토콜 확장 방식으로 이를 수행할 수 있습니다. removeObject()는 모든 유형의 .RangeReplaceableCollectionType( (특히)에 대해서Array가 '다'인 Equatable:

extension RangeReplaceableCollectionType where Generator.Element : Equatable {

    // Remove first collection element that is equal to the given `object`:
    mutating func removeObject(object : Generator.Element) {
        if let index = self.indexOf(object) {
            self.removeAtIndex(index)
        }
    }
}

예:

var ar = [1, 2, 3, 2]
ar.removeObject(2)
print(ar) // [1, 3, 2]

Swift 2 / Xcode 7 베타 2 업데이트: 코멘트에서 알 수 있듯이, Airspeed Velocity는 템플릿에서 보다 제한적인 범용 타입으로 메서드를 작성할 수 있게 되었습니다.이 때문에, 이 메서드는, 실제로, 다음의 확장으로서 정의될 수 있습니다.Array:

extension Array where Element : Equatable {
    
    // ... same method as above ...
}

프로토콜 확장은 더 큰 유형의 집합에 적용할 수 있다는 장점이 있습니다.

Swift 3 업데이트:

extension Array where Element: Equatable {
    
    // Remove first collection element that is equal to the given `object`:
    mutating func remove(object: Element) {
        if let index = index(of: object) {
            remove(at: index)
        }
    }
}

Swift 5 업데이트:

extension Array where Element: Equatable {
    
    /// Remove first collection element that is equal to the given `object` or `element`:
    mutating func remove(element: Element) {
        if let index = firstIndex(of: element) {
            remove(at: index)
        }
    }
}

템플릿에 더 제한적인 일반 유형에는 메서드를 쓸 수 없습니다.

메모: Swift 2.0부터는 템플릿에 보다 제한적인 메서드를 쓸 수 있게 되었습니다.코드를 2.0으로 업그레이드한 경우 확장을 사용하여 이를 구현하기 위한 새로운 옵션에 대한 다른 답변을 참조하십시오.

가 .'T' is not convertible to 'T'원래 T와 전혀 관련이 없는 새로운 T를 실제로 메서드에서 정의하고 있는 것입니다.메서드에 T를 사용하려면 메서드에 T를 지정하지 않고 T를 사용할 수 있습니다.

가 발생한 'AnyObject' is not convertible to 'T'T에 대해 가능한 모든 값이 모든 클래스가 아니라는 것입니다.인스턴스를 AnyObject로 변환하려면 클래스여야 합니다(구조체, 열거형 등일 수 없습니다).

배열을 인수로 받아들이는 함수로 만드는 것이 가장 좋습니다.

func removeObject<T : Equatable>(object: T, inout fromArray array: [T]) {
}

또는 원래 어레이를 수정하는 대신 다음 복사본을 반환하여 메서드를 보다 안전하고 재사용할 수 있습니다.

func arrayRemovingObject<T : Equatable>(object: T, fromArray array: [T]) -> [T] {
}

다른 방법으로는 배열에 저장된 유형을 메서드 템플릿으로 변환할 수 없는 경우 메서드를 자동으로 실패시킬 수 있습니다.(명확하게 하기 위해 메서드 템플릿에는 T 대신 U를 사용합니다).

extension Array {
    mutating func removeObject<U: Equatable>(object: U) {
        var index: Int?
        for (idx, objectToCompare) in enumerate(self) {
            if let to = objectToCompare as? U {
                if object == to {
                    index = idx
                }
            }
        }

        if(index != nil) {
            self.removeAtIndex(index!)
        }
    }
}

var list = [1,2,3]
list.removeObject(2) // Successfully removes 2 because types matched
list.removeObject("3") // fails silently to remove anything because the types don't match
list // [1, 3]

편집 사일런트 실패를 극복하려면 성공을 부울로 반환할 수 있습니다.

extension Array {
  mutating func removeObject<U: Equatable>(object: U) -> Bool {
    for (idx, objectToCompare) in self.enumerate() {  //in old swift use enumerate(self) 
      if let to = objectToCompare as? U {
        if object == to {
          self.removeAtIndex(idx)
          return true
        }
      }
    }
    return false
  }
}
var list = [1,2,3,2]
list.removeObject(2)
list
list.removeObject(2)
list

간결하고 간결하게:

func removeObject<T : Equatable>(object: T, inout fromArray array: [T]) 
{
    var index = find(array, object)
    array.removeAtIndex(index!)
}

위의 내용을 모두 읽어본 결과, 가장 좋은 답은 다음과 같습니다.

func arrayRemovingObject<U: Equatable>(object: U, # fromArray:[U]) -> [U] {
  return fromArray.filter { return $0 != object }
}

샘플:

var myArray = ["Dog", "Cat", "Ant", "Fish", "Cat"]
myArray = arrayRemovingObject("Cat", fromArray:myArray )

Swift 2(xcode 7b4) 어레이 확장:

extension Array where Element: Equatable {  
  func arrayRemovingObject(object: Element) -> [Element] {  
    return filter { $0 != object }  
  }  
}  

샘플:

var myArray = ["Dog", "Cat", "Ant", "Fish", "Cat"]
myArray = myArray.arrayRemovingObject("Cat" )

Swift 3.1 업데이트

Swift 3.1이 나왔기 때문에 다시 이 문제로 돌아왔습니다.다음은 완전하고 빠른 변환 및 변형을 제공하는 확장입니다.

extension Array where Element:Equatable {
    public mutating func remove(_ item:Element ) {
        var index = 0
        while index < self.count {
            if self[index] == item {
                self.remove(at: index)
            } else {
                index += 1
            }
        }
    }

    public func array( removing item:Element ) -> [Element] {
        var result = self
        result.remove( item )
        return result
    }
}

샘플:

// Mutation...
      var array1 = ["Cat", "Dog", "Turtle", "Cat", "Fish", "Cat"]
      array1.remove("Cat")
      print(array1) //  ["Dog", "Turtle", "Socks"]

// Creation...
      let array2 = ["Cat", "Dog", "Turtle", "Cat", "Fish", "Cat"]
      let array3 = array2.array(removing:"Cat")
      print(array3) // ["Dog", "Turtle", "Fish"]

프로토콜 확장을 사용하면 이 작업을 수행할 수 있습니다.

extension Array where Element: Equatable {
    mutating func remove(object: Element) {
        if let index = indexOf({ $0 == object }) {
            removeAtIndex(index)
        }
    }
}

클래스에 대해 동일한 기능,

스위프트 2

extension Array where Element: AnyObject {
    mutating func remove(object: Element) {
        if let index = indexOf({ $0 === object }) {
            removeAtIndex(index)
        }
    }
}

스위프트 3

extension Array where Element: AnyObject {
    mutating func remove(object: Element) {
        if let index = index(where: { $0 === object }) {
             remove(at: index)
        }
    }
}

그러나 클래스가 Equatable을 구현하면 애매해지고 컴파일러가 오류를 발생시킵니다.

swift 2.0에서 프로토콜 확장 기능 사용

extension _ArrayType where Generator.Element : Equatable{
    mutating func removeObject(object : Self.Generator.Element) {
        while let index = self.indexOf(object){
            self.removeAtIndex(index)
        }
    }
}

필터링을 사용하는 방법은 무엇입니까?다음은 [AnyObject]에서도 잘 작동합니다.

import Foundation
extension Array {
    mutating func removeObject<T where T : Equatable>(obj: T) {
        self = self.filter({$0 as? T != obj})
    }

}

질문을 못 알아들었나 봐요.

왜 안 먹힐까?

import Foundation
extension Array where Element: Equatable {
    mutating func removeObject(object: Element) {
        if let index = self.firstIndex(of: object) {
            self.remove(at: index)
        }
    }
}

var testArray = [1,2,3,4,5,6,7,8,9,0]
testArray.removeObject(object: 6)
let newArray = testArray

var testArray2 = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"]
testArray2.removeObject(object: "6")
let newArray2 = testArray2

확장 불필요:

var ra = [7, 2, 5, 5, 4, 5, 3, 4, 2]

print(ra)                           // [7, 2, 5, 5, 4, 5, 3, 4, 2]

ra.removeAll(where: { $0 == 5 })

print(ra)                           // [7, 2, 4, 3, 4, 2]

if let i = ra.firstIndex(of: 4) {
    ra.remove(at: i)
}

print(ra)                           // [7, 2, 3, 4, 2]

if let j = ra.lastIndex(of: 2) {
    ra.remove(at: j)
}

print(ra)                           // [7, 2, 3, 4]

제거할 개체의 일반 유형이 어레이 유형과 같을 수 없으므로 안전하지 않은 사용 없이 어레이에서 항목을 제거할 수 있습니다.그들은 매우 느리기 때문에 옵션을 사용하는 것도 완벽한 방법은 아니다.따라서 예를 들어 배열을 정렬할 때 이미 사용된 것처럼 폐쇄를 사용할 수 있습니다.

//removes the first item that is equal to the specified element
mutating func removeFirst(element: Element, equality: (Element, Element) -> Bool) -> Bool {
    for (index, item) in enumerate(self) {
        if equality(item, element) {
            self.removeAtIndex(index)
            return true
        }
    }
    return false
}

를 확장하면Array이 기능을 사용하여 다음을 수행하여 요소를 제거할 수 있습니다.

var array = ["Apple", "Banana", "Strawberry"]
array.removeFirst("Banana") { $0 == $1 } //Banana is now removed

단, 같은 메모리주소를 가지는 요소(클래스에 준거한 경우에만)를 삭제할 수 있습니다.AnyObject물론 프로토콜:

let date1 = NSDate()
let date2 = NSDate()
var array = [date1, date2]
array.removeFirst(NSDate()) { $0 === $1 } //won't do anything
array.removeFirst(date1) { $0 === $1 } //array now contains only 'date2'

좋은 점은 비교할 파라미터를 지정할 수 있다는 것입니다.예를 들어 배열이 있는 경우 등식 마감을 다음과 같이 지정할 수 있습니다.{ $0.count == $1.count }삭제할 어레이와 같은 크기의 첫 번째 어레이가 어레이에서 삭제됩니다.

다음과 같은 함수를 사용함으로써 함수 호출을 단축할 수도 있습니다.mutating func removeFirst(equality: (Element) -> Bool) -> Boolif-evaluation을 다음으로 바꿉니다.equality(item)그리고 함수를 호출합니다.array.removeFirst({ $0 == "Banana" })예를들면.

사용.indexOf대신for또는enumerate:

extension Array where Element: Equatable {

   mutating func removeElement(element: Element) -> Element? {
      if let index = indexOf(element) {
         return removeAtIndex(index)
      }
      return nil
   }

   mutating func removeAllOccurrencesOfElement(element: Element) -> Int {
       var occurrences = 0
       while true {
          if let index = indexOf(element) {
             removeAtIndex(index)
             occurrences++
          } else {
             return occurrences
          }
       }
   }   
}

나는 마침내 다음과 같은 코드를 갖게 되었다.

extension Array where Element: Equatable {

    mutating func remove<Element: Equatable>(item: Element) -> Array {
        self = self.filter { $0 as? Element != item }
        return self
    }

}

문제는 T가 의 어레이 유형과 관련이 없다는 것입니다.예를 들어 다음과 같습니다.

var array = [1,2,3,4,5,6]

array.removeObject(object:"four")

"6"은 Equatable이지만 Integer와 비교할 수 없는 유형입니다.

var array = [1,2,3,4,5,6]

extension Array where Element : Equatable {
    mutating func removeObject(object: Element) {
        filter { $0 != object }
    }
}

array.removeObject(object:"four")

문자열 배열이 아닌 명백한 이유로 removeObject를 호출할 때 오류가 발생합니다. 4를 제거하려면 다음 명령을 수행합니다.

array.removeObject(object:4)

또 다른 문제는 자체 수정 구조이므로 메서드에 라벨을 붙여야 하며 맨 위에 있는 참조는 var여야 합니다.

Swift 2에서의 구현:

extension Array {
  mutating func removeObject<T: Equatable>(object: T) -> Bool {
    var index: Int?
    for (idx, objectToCompare) in self.enumerate() {
      if let toCompare = objectToCompare as? T {
        if toCompare == object {
          index = idx
          break
        }
      }
    }
    if(index != nil) {
      self.removeAtIndex(index!)
      return true
    } else {
      return false
    }
  }
}

다음과 같은 작업을 수행할 수 있었습니다.

extension Array {
    mutating func removeObject<T: Equatable>(object: T) {
        var index: Int?
        for (idx, objectToCompare) in enumerate(self) {
            let to = objectToCompare as T
            if object == to {
                index = idx
            }
        }

        if(index) {
            self.removeAtIndex(index!)
        }
    }
}

언급URL : https://stackoverflow.com/questions/24938948/array-extension-to-remove-object-by-value

반응형