값을 기준으로 개체를 제거할 어레이 확장
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) -> Bool
if-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
'programing' 카테고리의 다른 글
파일이 Excel로 열려 있는 경우 pd.read_excel이 PermissionError를 발생시킵니다. (0) | 2023.04.12 |
---|---|
.svn 디렉토리를 무시하려면 어떻게 해야 하나요? (0) | 2023.04.12 |
개체 배열에서 속성 값 배열 가져오기 (0) | 2023.04.12 |
키-값 튜플 목록을 사전으로 변환하려면 어떻게 해야 합니까? (0) | 2023.04.12 |
변수 이름이 문자열로 저장되는 경우 변수 값을 얻는 방법은 무엇입니까? (0) | 2023.04.12 |