How to Use Contains Within a Swift Array Extension

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.

How can I use contains function in Array extension in Swift?

That contains overload only works when your elements are Equatable.

extension Sequence where Element: Equatable {
func addCheck(value: Element) {
print(
contains(value)
? "Element exists!"
: "Element does not exist!"
)
}
}

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)

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 
{
// ...
}

Array containsObject() extension

That means there is no need to use conditional cast. Remove the if let and change as? to as

extension Array {
func containsObject(_ object: Any) -> Bool {
for obj in self {
if obj as AnyObject === object as AnyObject {
return true
}
}
return false
}
}

Or simply:

extension Array {
func containsObject(_ object: Any) -> Bool {
return contains(where: {$0 as AnyObject === object as AnyObject})
}
}

How can I make a extension for array of specific type in Swift

for say the specific type is S

extension CollectionType where Generator.Element == S {
}

CollectionType Protocol

Extension for Array where Element is Optional

This is kind of tricky but you can create an AnyOptional protocol that requires an associatedtype (Wrapped) and a computed property to return the optional type. Then you can return the element unwrapped if the index is valid otherwise return nil.

protocol AnyOptional {
associatedtype Wrapped
var optional: Optional<Wrapped> { get }
}

extension Optional: AnyOptional {
var optional: Optional<Wrapped> { self }
}


extension Collection {
subscript(safe index: Index) -> Element? {
indices.contains(index) ? self[index] : nil
}
}


extension Collection  {
subscript(safe index: Index) -> Element.Wrapped? where Element: AnyOptional {
indices.contains(index) ? self[index].optional ?? nil : nil
}
}


var myArray: [String?] = ["2", "banana", nil, "31"]
var myStringArray: [String] = ["2", "3"]

let item = myArray[safe: 1] // item is String?
let strItem = myStringArray[safe: 99] // strItem is String?

How to extend an Array Double ?

If you want to map your array elements and need also its index position you should use the method enumerated(). I would also extend BidirectionalCollection instead of RandomAccessCollection and as already mentioned in comments by @Hamish using enumerated you can omit the Index == Int constraint.

protocol BidirectionalCollection : BidirectionalIndexable, Collection

Description: A collection that supports backward as well as forward
traversal. Bidirectional collections offer traversal backward from any
valid index, not including a collection’s startIndex. Bidirectional
collections can therefore offer additional operations, such as a last
property that provides efficient access to the last element and a
reversed() method that presents the elements in reverse order. In
addition, bidirectional collections have more efficient
implementations of some sequence and collection methods, such as
suffix(_:).

extension BidirectionalCollection where Iterator.Element == Double, IndexDistance == Int {
public func applyWindowing() -> [Iterator.Element] {
return enumerated().map{ $0.element * windowingFunc(index: $0.offset, N: count)}
}
}


Related Topics



Leave a reply



Submit