[ios] 값으로 객체를 제거하는 배열 확장
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’로 변환 할 수 없습니다
이를 수행하는 올바른 방법은 무엇입니까?
답변
현재 스위프트 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 ...
}
프로토콜 확장은 더 큰 유형의 세트에 적용 할 수 있다는 장점이 있습니다.
스위프트 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)
}
}
}
답변
템플릿에서 더 제한적인 제네릭 형식에는 메서드를 작성할 수 없습니다.
참고 : 스위프트 2.0로, 당신은 지금 방법을 쓸 수 있는 템플릿에 대한 제한을. 코드를 2.0으로 업그레이드 한 경우 확장을 사용하여이를 구현할 수있는 새로운 옵션에 대해서는 다른 답변을 참조하십시오.
오류 'T' is not convertible to 'T'
가 발생하는 이유 는 실제로 새 것을 정의하고 있기 때문입니다. 원래 T와 전혀 관련이없는 메소드에서 T를 있기 때문입니다. 메소드에서 T를 사용하려는 경우 메소드에서 지정하지 않고 그렇게 할 수 있습니다.
두 번째 오류 'AnyObject' is not convertible to 'T'
가 발생하는 이유는 T에 가능한 모든 값이 모든 클래스가 아니기 때문입니다. 인스턴스를 AnyObject로 변환하려면 클래스 여야합니다 (struct, enum 등일 수 없음).
가장 좋은 방법은 배열을 인수로 허용하는 함수로 만드는 것입니다.
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 )
스위프트 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" )
스위프트 3.1 업데이트
이제 스위프트 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})
}
}