Comparing Objects in an Array Extension Causing Error in Swift

Comparing objects in an Array extension causing error in Swift

You can always create an extension that uses NSArray's indexOfObject, e.g:

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

You can specify that your array items can be compared with the <T : Equatable> constraint, then you can cast your object into T and compare them, e.g:

extension Array {
func indexOfObject<T : Equatable>(o:T) -> Int? {
if self.count > 0 {
for (idx, objectToCompare) in enumerate(self) {
let to = objectToCompare as T
if o == to {
return idx
}
}
}

return nil
}
}

Unable to use contains within a Swift Array extension

Swift 1.x

The elements in an array don't have to be Equatable, i.e. they don't have be comparable with ==.

That means you can't write that function for all possible Arrays. And Swift doesn't allow you to extend just a subset of Arrays.

That means you should write it as a separate function (and that's probably why contains isn't a method, either).

let array = ["a", "b", "c", "a"]

func distinct<T: Equatable>(array: [T]) -> [T] {
var rtn = [T]()

for x in array {
var containsItem = contains(rtn, x)
if !containsItem {
rtn.append(x)
}
}
return rtn
}

distinct(array) // ["a", "b", "c"]

Update for Swift 2/Xcode 7 (Beta)

Swift 2 supports restricting extensions to a subset of protocol implementations, so the following is now allowed:

let array = ["a", "b", "c", "a"]

extension SequenceType where Generator.Element: Comparable {
func distinct() -> [Generator.Element] {
var rtn: [Generator.Element] = []

for x in self {
if !rtn.contains(x) {
rtn.append(x)
}
}
return rtn
}
}

array.distinct() // ["a", "b", "c"]

Note how apple added SequenceType.contains using the same syntax.

Swift contains extension for Array

you don't actually need to write an extension, you can use the global func contains from the Swift library:

contains([1,2,3], 1)

Compare two objects in Swift

You want Comparable, not Equatable. Equatable only has ==.

Swift extension of ArrayMutableCollection won't allow reverse()

First of all, the extension should be declared like this:

extension Array where Element : MutableCollection {

You want to check that Element adheres to the protocol MutableCollection, not that it is a MutableCollection

However, then I'm not able to call the reverse method on the subscript for some reason. The best I've been able to do is this:

extension Array where Element : MutableCollection {
mutating func mirror() {
for index in self.indices {
self[index] = self[index].reversed() as! Element
}
}
}

Which works as you need it to work although the forced cast is very ugly and I dislike doing it. I suppose I should test the cast to be certain but I can't see any case where calling reversed() would result in a collection that couldn't be cast back to Element.

Edit:

I figured out the issue. The reverse() method is only valid on MutableCollection when it is also a BidirectionalCollection. This code now works correctly:

extension MutableCollection where
Iterator.Element : MutableCollection &
BidirectionalCollection,
Indices.Iterator.Element == Index {
mutating func mirror() {
for index in self.indices {
self[index].reverse()
}
}
}

Now the code should work for all MutableCollection whose elements are both a MutableCollection and BidirectionalCollection - such as [Array<Int>] or even [ArraySlice<Int>]

You can see the full code for reverse() in Swift 3.1 here:

Reverse.swift

extension MutableCollection where Self : BidirectionalCollection

How can I extend typed Arrays in Swift?

For extending typed arrays with classes, the below works for me (Swift 2.2). For example, sorting a typed array:

class HighScoreEntry {
let score:Int
}

extension Array where Element == HighScoreEntry {
func sort() -> [HighScoreEntry] {
return sort { $0.score < $1.score }
}
}

Trying to do this with a struct or typealias will give an error:

Type 'Element' constrained to a non-protocol type 'HighScoreEntry'

Update:

To extend typed arrays with non-classes use the following approach:

typealias HighScoreEntry = (Int)

extension SequenceType where Generator.Element == HighScoreEntry {
func sort() -> [HighScoreEntry] {
return sort { $0 < $1 }
}
}

In Swift 3 some types have been renamed:

extension Sequence where Iterator.Element == HighScoreEntry 
{
// ...
}

Provide a catch if index is out of range (Swift 5)

You can use indices to check if an array contains an index prior to accessing it:

guard myArray.indices.contains(1) else { return }
let value = myArray[1]

Apple documentation: indices



Related Topics



Leave a reply



Submit