array remove

Hello,


What is the situation regarding the "remove item from array" problem in Swift 2.0?


Of course there is the find index function in the language guide (an example of generics) but that's not very object-oriented


On Stackoverflow I have seen two answers:


1. Make an Array extension that bridges to NSArray and use indexOfObject (ugly, but works in Swift 1.2 too)

2. Extend the

RangeReplaceableCollectionType protocol in Swift 2.0


extension RangeReplaceableCollectionType where Generator.Element : Equatable { mutating func removeObject(object:Self.Generator.Element) { if let found = self.indexOf(object) { self.removeAtIndex(found) } } }


Does this really work?


It would be so much nicer if you could do


extension Array<T:Equatable>

{

mutating func removeItem<T:Equatable>(item:T) { if let index = find(self,object) {removeAtIndex(index) }}

}


in order to have a removeItem method for arrays of an Equatable type


Jan E.

Please pretty-print the code snippets you paste:

extension RangeReplaceableCollectionType where Generator.Element : Equatable {
    mutating func removeObject(object: Self.Generator.Element) {
        if let found = self.indexOf(object) {
            self.removeAtIndex(found)
        }
    }
}

(I think `removeObject` is not an appropriate name, as `object` can be a primitive type value.)

Does this really work?

Make it try.

var intArr = [1, 2, 3, 4]
intArr.removeObject(3)
print(intArr) //->[1,2,4]


Making your code corrected for Swift 2.

extension Array where Element: Equatable { //Proper syntax for generic constraint in Swift 2
    mutating func removeItem(item: Element) { //No need to make removeItem method generic, as Array itself is generic
        if let index = self.indexOf(item) { //Swift 2 does not have find function.
            removeAtIndex(index)
        }
    }
}

Very similar to the `removeObject` method.


The difference is, your extension only works for Arrays, the first extension works for all types conforming to RangeReplaceableCollectionType including Arrays.

var chars = "abcd".characters
chars.removeObject("b")
print(String(chars)) //"acd"
chars.removeItem("c") //error: 'String.CharacterView' does not have a member named 'removeItem'

Can I use this editor to pretty-print?

When pasting from TextEdit rich text I loose all formatting.

Is there a simple html example somewhere?

Use the <> button in the toolbar right above where you are typing the post to create a code element, then paste (or type) in there.

The code editor invoked with `<>` sometimes becomes an ugly editor with two insertion-point cursors and actual insersion point unpredictable...


When I use pasting in the code editor, I only use codes copied from Xcode editor.

So here is my pretty-printed answer:


Thank you for your clear answer.

Since I am still on Swift 1.2 I’ll use this:


func MyRemoveObjectFromArray<T:AnyObject>( inout array:[T], item:T )
  {
  if let itemIndex = MyFindObjectIndexInArray( array, item ) { array.removeAtIndex( itemIndex ) }
  }

func MyFindObjectIndexInArray<T:AnyObject>( array:[T], item:T )->Int?
  {
  var itemIndex:Int?
  for var curIndex = 0; curIndex < array.count; curIndex++
    {
    if array[curIndex] === item { itemIndex = curIndex }
    }

  return itemIndex
  }


This way I can avoid implementing the Equatable protocol for my classes (assuming pointer equality is good enough).


On Swift 2.0 I’ll go for the RangeReplaceableCollectionType protocol:


extension RangeReplaceableCollectionType where Generator.Element:Equatable
  {
  mutating func removeItem(item: Self.Generator.Element)
    {
    if let itemIndex = self.indexOf(item) { self.removeAtIndex(itemIndex) }
    }
  }

extension RangeReplaceableCollectionType where Generator.Element:AnyObject
  {
  mutating func removeObject(object: Self.Generator.Element)
    {
    if let itemIndex = MyFindObjectIndexInArray(self,object) { self.removeAtIndex(itemIndex) }
    }


Not battle-tested yet!

Thanks for sharing your solution.

By the way, MyFindObjectIndexInArray returns the last index found, different behavior from find function or indexOf method.

var arr = [1, 2, 3, 1]
print(find(arr, 1)) //->Optional(0)
print(MyFindObjectIndexInArray(arr, 1))//-->Optional(3)

(Utilizing automatic conversion from [Int] to [NSNumber].)

array remove
 
 
Q