func getIndex<T: Equatable>(valueToFind: T) -> Int? {...}
mutating func replaceObjectWithObject<T: Equatable>(obj1: T, obj2: T) {
if let index = self.getIndex(obj1) {
self.removeAtIndex(index)
self.insert(obj2, atIndex: index) // Error here: 'T' is not convertible to 'T'
}
}
I have that function which is suppose to replace an element with another element. But Im not very familiar with Generics and don't know why this is not working. Please help.
If I remove the Equatable from the mutating func the error message jumps to the first line in that func and if I then replace that with the func find() that gives me the same error as on line 3.
This is actually not possible via an extension under the existing system of protocols and generics in Swift - you can't add additional constraints to the generic subtype of a type, so you can't extend Array with a method that requires that its contents conform to Equatable.
You can see this restriction in action with the built-in Array type -- there's no myArray.find(element) method, but there is a global function find() that takes a collection and an element, with a generic constraint that the collection's elements are Equatable:
func find<C : CollectionType where C.Generator.Element : Equatable>(domain: C, value: C.Generator.Element) -> C.Index?
You can do this for your method - you just need to write a similar top-level function:
func replaceObjectWithObject<C : RangeReplaceableCollectionType where C.Generator.Element : Equatable>(inout collection: C, obj1: C.Generator.Element, obj2: C.Generator.Element) {
if let index = find(collection, obj1) {
removeAtIndex(&collection, index)
insert(&collection, obj2, atIndex: index)
}
}
var myArray = [1, 2, 3, 4, 5]
replaceObjectWithObject(&myArray, 2, 7)
// 1, 2, 7, 4, 5
How did you declare your Array extension? The problem is that your generic functions require arguments of type Equatable, but when you declared the array, you specified a specific implementation of an Equatable class, like String. A T is not a String without a cast.
What you are trying to do cannot be done using class/struct functions - #Nate Cook has provided a very good solution using a global function.
By the way the reason why it doesn't work becomes clearer if in your extension methods you replace T with V: they are different types. That also explains why the same error occurs if you remove the dependency from Equatable: the array holds objects of T type, but you are trying to insert a V value.
This answer is for a duplicate question stated her: Create swift array extension for typed arrays
There is a way to solve extensions to Array that are only applicable to a specific type of array. But you have to use an Array with elements of type Any, which sort of circumvents Swift's type system. But the code still works even if there are elements of other types in the array. See example below.
class Job {
var name: String
var id: Int
var completed: Bool
init(name: String, id: Int, completed: Bool) {
self.name = name
self.id = id
self.completed = completed
}
}
var jobs: [Any] = [
Job(name: "Carpenter", id: 32, completed: true),
Job(name: "Engineer", id: 123, completed: false),
Job(name: "Pilot", id: 332, completed: true)]
extension Array {
// These methods are intended for arrays that contain instances of Job
func withId(id: Int) -> Job? {
for j in self {
if (j as? Job)?.id == id {
return j as? Job
}
}
return nil
}
func thatAreCompleted() -> [Job] {
let completedJobs = self.filter { ($0 as? Job) != nil && ($0 as? Job)!.completed}
return completedJobs.map { $0 as! Job }
}
}
jobs.withId(332)
println(jobs.withId(332)?.name)
//prints "Optional("Pilot")"
let completedJobs = jobs.thatAreCompleted().map {$0.name}
println(completedJobs)
//prints "[Carpenter, Pilot]"
You can use extension with a where clause constraint and I'm using Xcode 7.3.1
extension Array where Element: Equatable {
func testEqutability() {
let e1 = self[0]
let e2 = self[1]
if e1 == e2 {//now we can use == to test Element equtability
//do something
}
}
}
Related
I have a String like LINNIIBDDDN, basically a series of tokens. I'd like to use multiple iterators, one for each token type. I'd like to have each iterator ignore the tokens that don't belong to it. That is, I want to call something like next_ish(), to advance the iterator to the next element of its particular token. So if the Niterator is at index 3, and I call next_ish(), I want it to go to index 10, the next N, not the I at index 4. I have some code that already works, but it's a lot of code, it makes the String into an array, and I have subclassed iterators, basically hand-written, with no help from Swift, although I'm sure the Swift iterators are more stable and thoroughly tested. I'd rather use their code than mine, where possible.
It seems like it should be easy just to extend String.Iterator and add next_ish(), but I'm at a loss. My first naive attempt was to extend String.Iterator. I get the error Constrained extension must be declared on the unspecialized generic type 'IndexingIterator' with constraints specified by a 'where' clause. I went looking to figure out what kind of where clause to use, and I haven't found anything.
There are a lot of answers here on SO, about extending arrays and generics, pulling all the elements of a certain type into an array of their own, even some answers about specialized for...in loops, but I can't find anything about extending iterators. I've read through Collections.swift and haven't found anything helpful. Is it possible to extend String.Iterator? That would make my life a lot easier. If not, is there some sort of built-in Swift mechanism for doing this sort of thing?
String.Iterator is (implicitly) defined as
typealias Iterator = IndexingIterator<String>
and the error message
Constrained extension must be declared on the unspecialized generic type 'IndexingIterator' with constraints specified by a 'where' clause
means that we must define extension methods as
extension IndexingIterator where Elements == String { }
Alternatively (with increasing generality):
extension IndexingIterator where Elements: StringProtocol { }
extension IndexingIterator where Elements.Element == Character { }
I haven't found a way to access the underlying collection (or position)
from within an extension method, the corresponding members are defined as
“internal”:
public struct IndexingIterator<Elements : Collection> {
internal let _elements: Elements
internal var _position: Elements.Index
// ...
}
What you can do is to pass the wanted element to your “next-ish” method,
either as the element itself, or as a predicate:
extension IndexingIterator where Elements.Element == Character {
mutating func next(_ wanted: Character) -> Character? {
while let c = next() {
if c == wanted { return c }
}
return nil
}
mutating func next(where predicate: ((Character) -> Bool)) -> Character? {
while let c = next() {
if predicate(c) { return c }
}
return nil
}
}
Example usage:
var it1 = "ABCDABCE".makeIterator()
print(it1.next("C") as Any) // Optional("C")
print(it1.next() as Any) // Optional("D")
print(it1.next("C") as Any) // Optional("C")
print(it1.next() as Any) // Optional("E")
print(it1.next("C") as Any) // nil
var it2 = "LINnIIBDDDN".makeIterator()
while let c = it2.next(where: { "Nn".contains($0) }) {
print(c, terminator: ", ")
}
print()
// N, n, N,
But actually I would consider String.Iterator being an IndexingIterator an implementation detail, and extend the IteratorProtocol instead:
extension IteratorProtocol where Element: Equatable {
mutating func next(_ wanted: Element) -> Element? {
while let e = next() {
if e == wanted { return e }
}
return nil
}
}
extension IteratorProtocol {
mutating func next(where predicate: ((Element) -> Bool)) -> Element? {
while let e = next() {
if predicate(e) { return e }
}
return nil
}
}
That makes it usable for arbitrary sequences. Example:
var it3 = [1, 1, 2, 3, 5, 8, 13, 21, 34].makeIterator()
while let e = it3.next(where: { $0 % 2 == 0} ) {
print(e, terminator: ", ")
}
print()
// 2, 8, 34,
How can we create unique object list in Swift language like NSSet & NSMutableSet in Objective-C.
As of Swift 1.2 (Xcode 6.3 beta), Swift has a native set type.
From the release notes:
A new Set data structure is included which provides a generic
collection of unique elements, with full value semantics. It bridges
with NSSet, providing functionality analogous to Array and Dictionary.
Here are some simple usage examples:
// Create set from array literal:
var set = Set([1, 2, 3, 2, 1])
// Add single elements:
set.insert(4)
set.insert(3)
// Add multiple elements:
set.unionInPlace([ 4, 5, 6 ])
// Swift 3: set.formUnion([ 4, 5, 6 ])
// Remove single element:
set.remove(2)
// Remove multiple elements:
set.subtractInPlace([ 6, 7 ])
// Swift 3: set.subtract([ 6, 7 ])
print(set) // [5, 3, 1, 4]
// Test membership:
if set.contains(5) {
print("yes")
}
but there are far more methods available.
Update: Sets are now also documented in the "Collection Types" chapter of the Swift documentation.
You can use any Objective-C class in Swift:
var set = NSMutableSet()
set.addObject(foo)
Swift has no concept of sets. Using NSMutableSet in Swift might be slower than using a Dictionary that holds dummy values. You could do this :
var mySet: Dictionary<String, Boolean> = [:]
mySet["something"]= 1
Then just iterate over the keys.
I've built an extensive Set type similar to the built-in Array and Dictionary - here are blog posts one and two and a GitHub repository:
Creating a Set Type in Swift
Set Type Follow-up
SwiftSets on GitHub
extension Array where Element: Hashable {
var setValue: Set<Element> {
return Set<Element>(self)
}
}
let numbers = [1,2,3,4,5,6,7,8,9,0,0,9,8,7]
let uniqueNumbers = numbers.setValue // {0, 2, 4, 9, 5, 6, 7, 3, 1, 8}
let names = ["John","Mary","Steve","Mary"]
let uniqueNames = names.setValue // {"John", "Mary", "Steve"}
I thought a struct with an internal Dictionary would be the way to go. I have only just started using it, so it’s not complete and I have no idea on performance yet.
struct Set<T : Hashable>
{
var _items : Dictionary<T, Bool> = [:]
mutating func add(newItem : T) {
_items[newItem] = true
}
mutating func remove(newItem : T) {
_items[newItem] = nil
}
func contains(item: T) -> Bool {
if _items.indexForKey(item) != nil { return true } else { return false }
}
var items : [T] { get { return [T](_items.keys) } }
var count : Int { get { return _items.count } }
}
You actually can create a Set object pretty easy (in contradiction to GoZoner, there is a built in contains method):
class Set<T : Equatable> {
var items : T[] = []
func add(item : T) {
if !contains(items, {$0 == item}) {
items += item
}
}
}
and you maybe even want to declare a custom operator:
#assignment #infix func += <T : Equatable> (inout set : Set<T>, items : T[]) -> Set<T> {
for item in items {
set.add(item)
}
return set
}
Always in such a case the critical factor is how to compare objects and what types of objects go into the Set. Using a Swift Dictionary, where the Set objects are the dictionary keys, could be a problem based on the restrictions on the key type (String, Int, Double, Bool, valueless Enumerations or hashable).
If you can define a hash function on your object type then you can use a Dictionary. If the objects are orderable, then you could define a Tree. If the objects are only comparable with == then you'll need to iterate over the set elements to detect a preexisting object.
// When T is only Equatable
class Set<T: Equatable> {
var items = Array<T>()
func hasItem (that: T) {
// No builtin Array method of hasItem...
// because comparison is undefined in builtin Array
for this: T in items {
if (this == that) {
return true
}
}
return false
}
func insert (that: T) {
if (!hasItem (that))
items.append (that)
}
}
The above is an example of building a Swift Set; the example used objects that are only Equatable - which, while a common case, doesn't necessarily lead to an efficient Set implementations (O(N) search complexity - the above is an example).
So I think creating a Set with an array is a terrible idea - O(n) is the time complexity of that set.
I have put together a nice Set that uses a dictionary: https://github.com/evilpenguin/Swift-Stuff/blob/master/Set.swift
I wrote a function to solve this problem.
public func removeDuplicates<C: ExtensibleCollectionType where C.Generator.Element : Equatable>(aCollection: C) -> C {
var container = C()
for element in aCollection {
if !contains(container, element) {
container.append(element)
}
}
return container
}
To use it, just pass an array which contains duplicate elements to this function. And then it will return a uniqueness-guaranteed array.
You also can pass a Dictionary, String or anything conforms to ExtensibleCollectionType protocol if you like.
Special case for classes derived from NSObject
given that default Equitable (& Hashable) conformance in NSObject is basically trash you'd better make sure you provide a proper
static func == (lhs: YourClassDerivedFromNSObject, rhs: YourClassDerivedFromNSObject) -> Bool {
implementation lest you want plucking the duplicates inserted into
Set
for example:
var a = [1, 2, 3] // Ints
var s = ",".join(a) // EXC_BAD_ACCESS
Is it possible to make the join function return "1,2,3" ?
Extend Int (or other custom types) to conform to some protocols ?
From Xcode 7.0 beta 6 in Swift 2 now you should use [String].joinWithSeparator(",").
In your case you still need to change Int to String type, therefore I added map().
var a = [1, 2, 3] // [1, 2, 3]
var s2 = a.map { String($0) }.joinWithSeparator(",") // "1,2,3"
From Xcode 8.0 beta 1 in Swift 3 code slightly changes to
[String].joined(separator: ",").
var s3 = a.map { String($0) }.joined(separator: ",") // "1,2,3"
try this
var a = [1, 2, 3] // Ints
var s = ",".join(a.map { $0.description })
or add this extension
extension String {
func join<S : SequenceType where S.Generator.Element : Printable>(elements: S) -> String {
return self.join(map(elements){ $0.description })
}
// use this if you don't want it constrain to Printable
//func join<S : SequenceType>(elements: S) -> String {
// return self.join(map(elements){ "\($0)" })
//}
}
var a = [1, 2, 3] // Ints
var s = ",".join(a) // works with new overload of join
join is defined as
extension String {
func join<S : SequenceType where String == String>(elements: S) -> String
}
which means it takes a sequence of string, you can't pass a sequence of int to it.
And just to make your life more complete, starting from Xcode 8.0 beta 1 in Swift 3 you should NOW use [String].joined(separator: ",").
This is the new "ed/ing" naming rule for Swift APIs:
Name functions and methods according to their side-effects
Those without side-effects should read as noun phrases, e.g. x.distance(to: y), i.successor().
Those with side-effects should read as imperative verb phrases, e.g., print(x), x.sort(), x.append(y).
Name Mutating/nonmutating method pairs consistently. A mutating method will often have a nonmutating variant with similar semantics, but that returns a new value rather than updating an instance in-place.
Swift: API Design Guidelines
The simplest way is a variation of #BryanChen's answer:
",".join(a.map { String($0) } )
Even if you can't make join work for custom types, there's an easy workaround.
All you have to do is define a method on your class (or extend a built-in class) to return a string, and then map that into the join.
So, for example, we could have:
extension Int {
func toString() -> String {
return "\(self)" // trivial example here, but yours could be more complex
}
Then you can do:
let xs = [1, 2, 3]
let s = join(xs.map { $0.toString() })
I wouldn't recommend using .description for this purpose, as by default it will call .debugDescription, which is not particularly useful in production code.
In any case, it would be better to provide an explicit method for transforming into a string suitable for joining, rather than relying on a generic 'description' method which you may change at a later date.
A Swift 3 solution
public extension Sequence where Iterator.Element: CustomStringConvertible {
func joined(seperator: String) -> String {
return self.map({ (val) -> String in
"\(val)"
}).joined(separator: seperator)
}
}
I am curious how to do a for loop with a tuple in swift.
I know that to access each member you can use dot notation using the index number
var tupleList = ("A",2.9,3,8,5,6,7,8,9)
for each in tupleList {
println(each)
}
//Error: Type does not conform to protocol sequence
Yes, you can!
func iterate<C,R>(t:C, block:(String,Any)->R) {
let mirror = reflect(t)
for i in 0..<mirror.count {
block(mirror[i].0, mirror[i].1.value)
}
}
And voila!
let tuple = ((false, true), 42, 42.195, "42.195km")
iterate(tuple) { println("\($0) => \($1)") }
iterate(tuple.0){ println("\($0) => \($1)")}
iterate(tuple.0.0) { println("\($0) => \($1)")} // no-op
Note the last one is not a tuple so nothing happens (though it is a 1-tuple or "Single" which content can be accessed .0, reflect(it).count is 0).
What's interesting is that iterate() can iterate even other types of collection.
iterate([0,1]) { println("\($0) => \($1)") }
iterate(["zero":0,"one":1]) { println("\($0) => \($1)") }
And that collection includes class and struct!
struct Point { var x = 0.0, y = 0.0 }
class Rect { var tl = Point(), br = Point() }
iterate(Point()) { println("\($0) => \($1)") }
iterate(Rect()) { println("\($0) => \($1)") }
Caveat: the value passed as the 2nd argument of the block is type Any. You have to cast it back to the values with original type.
You can using reflection Swift 5
Try this in a Playground:
let tuple = (1, 2, "3")
let tupleMirror = Mirror(reflecting: tuple)
let tupleElements = tupleMirror.children.map({ $0.value })
tupleElements
Output:
Swift does not currently support iterating over tuples.
The biggest reasons are:
There is no way at runtime to determine the number of elements in a tuple
There is no way to access an element at a specific index except for the compile time accessors like tupleList.0. You would really want a subscript tupleList[0] but that is not provided to us
Frankly, I can't see a reason that you would use a tuple instead of an Array if you want to iterate over it.
It doesn't make sense to iterate over a tuple because:
Tuples always have a fixed length and each element has a fixed type
You can name each tuple member with a name you can use to access it later
Arrays are well made to iterate over:
Arbitrary length
Can store multiple types using a common superclass or AnyObject
Can be declared as a literal in a similar fashion to tuples: var list = ["A",2.9,3,8,5,6,7,8,9]
#dankogai's excellent solution, updated for Swift 3.0:
func iterate<Tuple>(_ tuple:Tuple, body:(_ label:String?,_ value:Any)->Void) {
for child in Mirror(reflecting: tuple).children {
body(child.label, child.value)
}
}
Usage remains identical to #dankogai's examples (beyond Swift 2's println()→print() rename).
Note that the label is now of type String? when it was formerly String, to match the type change from Swift 1's MirrorType.subscript(…).0 to Swift 3's Mirror.Child.label. However, for labelless tuples the label arg comes back as ".0", ".1", ".2", etc.— it's only nil for some other types.
Also, I took the liberty of renaming types & args to better match Swift 3's solidified naming standards, and changing the closure return type to Void.
Sidenote: I noticed somebody downvoted me here— I can't imagine why, other than the (fair) argument that building app functionality around reflection in Swift is hacking the type system, and is likely to lead to crappy code throughout (Swift's tuples shouldn't be considered an abstract data type, but rather a small collection of variables, akin to method args). As a counter-argument, I originally ended up porting this to Swift 3 in project because I needed it— for better descriptions and debugDescriptions. Because sane debug output will saves you hours and hours of frustration. ;-) Additionally, this could be really useful for unit tests… because tests are ultimately most interested in “did the result of this operation match what we expect?”
Details
Xcode 11.2.1 (11B500), Swift 5.1
Base Solution
struct Tuple<T> {
let original: T
private let array: [Mirror.Child]
init(_ value: T) {
self.original = value
array = Array(Mirror(reflecting: original).children)
}
func forEach(closure: (Mirror.Child) -> Void) { array.forEach { closure($0) } }
func getOnlyValues<T: Any>() -> [T] { array.compactMap { $0.value as? T } }
func getAllValues() -> [Any] { array.compactMap { $0.value } }
}
Usage on base solution
let num: Int? = 3
let str: String? = nil
let x = (1, "stew", str, 5.4, 2, num)
let tuple = Tuple(x)
tuple.forEach { print("\($0)") }
print("\(tuple.getAllValues())") // [1, "stew", nil, 5.4, 2, Optional(3)]
print("\(tuple.getOnlyValues() as [Int])") // [1, 2, 3]
More sugar
func valuesFrom<V>(tuple: V) -> [Any] { return Tuple(tuple).getAllValues() }
func onlyValuesFrom<T,V>(tuple: V) -> [T] { return Tuple(tuple).getOnlyValues() as [T] }
print(valuesFrom(tuple: x)) // [1, "stew", nil, 5.4, 2, Optional(3)]
print(onlyValuesFrom(tuple: x) as [Int]) // [1, 2, 3]
No, you can't. The reason is that tuple items are not all required to have the same type, so you would not be able to know what type each should have.
How can we create unique object list in Swift language like NSSet & NSMutableSet in Objective-C.
As of Swift 1.2 (Xcode 6.3 beta), Swift has a native set type.
From the release notes:
A new Set data structure is included which provides a generic
collection of unique elements, with full value semantics. It bridges
with NSSet, providing functionality analogous to Array and Dictionary.
Here are some simple usage examples:
// Create set from array literal:
var set = Set([1, 2, 3, 2, 1])
// Add single elements:
set.insert(4)
set.insert(3)
// Add multiple elements:
set.unionInPlace([ 4, 5, 6 ])
// Swift 3: set.formUnion([ 4, 5, 6 ])
// Remove single element:
set.remove(2)
// Remove multiple elements:
set.subtractInPlace([ 6, 7 ])
// Swift 3: set.subtract([ 6, 7 ])
print(set) // [5, 3, 1, 4]
// Test membership:
if set.contains(5) {
print("yes")
}
but there are far more methods available.
Update: Sets are now also documented in the "Collection Types" chapter of the Swift documentation.
You can use any Objective-C class in Swift:
var set = NSMutableSet()
set.addObject(foo)
Swift has no concept of sets. Using NSMutableSet in Swift might be slower than using a Dictionary that holds dummy values. You could do this :
var mySet: Dictionary<String, Boolean> = [:]
mySet["something"]= 1
Then just iterate over the keys.
I've built an extensive Set type similar to the built-in Array and Dictionary - here are blog posts one and two and a GitHub repository:
Creating a Set Type in Swift
Set Type Follow-up
SwiftSets on GitHub
extension Array where Element: Hashable {
var setValue: Set<Element> {
return Set<Element>(self)
}
}
let numbers = [1,2,3,4,5,6,7,8,9,0,0,9,8,7]
let uniqueNumbers = numbers.setValue // {0, 2, 4, 9, 5, 6, 7, 3, 1, 8}
let names = ["John","Mary","Steve","Mary"]
let uniqueNames = names.setValue // {"John", "Mary", "Steve"}
I thought a struct with an internal Dictionary would be the way to go. I have only just started using it, so it’s not complete and I have no idea on performance yet.
struct Set<T : Hashable>
{
var _items : Dictionary<T, Bool> = [:]
mutating func add(newItem : T) {
_items[newItem] = true
}
mutating func remove(newItem : T) {
_items[newItem] = nil
}
func contains(item: T) -> Bool {
if _items.indexForKey(item) != nil { return true } else { return false }
}
var items : [T] { get { return [T](_items.keys) } }
var count : Int { get { return _items.count } }
}
You actually can create a Set object pretty easy (in contradiction to GoZoner, there is a built in contains method):
class Set<T : Equatable> {
var items : T[] = []
func add(item : T) {
if !contains(items, {$0 == item}) {
items += item
}
}
}
and you maybe even want to declare a custom operator:
#assignment #infix func += <T : Equatable> (inout set : Set<T>, items : T[]) -> Set<T> {
for item in items {
set.add(item)
}
return set
}
Always in such a case the critical factor is how to compare objects and what types of objects go into the Set. Using a Swift Dictionary, where the Set objects are the dictionary keys, could be a problem based on the restrictions on the key type (String, Int, Double, Bool, valueless Enumerations or hashable).
If you can define a hash function on your object type then you can use a Dictionary. If the objects are orderable, then you could define a Tree. If the objects are only comparable with == then you'll need to iterate over the set elements to detect a preexisting object.
// When T is only Equatable
class Set<T: Equatable> {
var items = Array<T>()
func hasItem (that: T) {
// No builtin Array method of hasItem...
// because comparison is undefined in builtin Array
for this: T in items {
if (this == that) {
return true
}
}
return false
}
func insert (that: T) {
if (!hasItem (that))
items.append (that)
}
}
The above is an example of building a Swift Set; the example used objects that are only Equatable - which, while a common case, doesn't necessarily lead to an efficient Set implementations (O(N) search complexity - the above is an example).
So I think creating a Set with an array is a terrible idea - O(n) is the time complexity of that set.
I have put together a nice Set that uses a dictionary: https://github.com/evilpenguin/Swift-Stuff/blob/master/Set.swift
I wrote a function to solve this problem.
public func removeDuplicates<C: ExtensibleCollectionType where C.Generator.Element : Equatable>(aCollection: C) -> C {
var container = C()
for element in aCollection {
if !contains(container, element) {
container.append(element)
}
}
return container
}
To use it, just pass an array which contains duplicate elements to this function. And then it will return a uniqueness-guaranteed array.
You also can pass a Dictionary, String or anything conforms to ExtensibleCollectionType protocol if you like.
Special case for classes derived from NSObject
given that default Equitable (& Hashable) conformance in NSObject is basically trash you'd better make sure you provide a proper
static func == (lhs: YourClassDerivedFromNSObject, rhs: YourClassDerivedFromNSObject) -> Bool {
implementation lest you want plucking the duplicates inserted into
Set