Generic Extension to Array Not Working - swift

I've been playing around with Generics and Extensions to existing types in Swift 3. I wrote two generic Array functions that extends Array with find-and-replace methods, named replaced() and replace(). The replaced() function works as intended but the replace() function has a compile time error. Here is the code and a test of one of the methods.
extension Array {
func replaced<T: Equatable>(each valueToReplace: T, with newValue: T) -> [T] {
var newArray:[T] = []
for index:Int in 0..<self.count {
if let temp = self[index] as? T, temp == valueToReplace{
newArray.append(newValue)
}else{
newArray.append(self[index] as! T)
}
}
return newArray
}
mutating func replace<T: Equatable>(each valueToReplace: T, with newValue: T) {
for index:Int in 0..<self.count {
if let temp = self[index] as? T, temp == valueToReplace {
// FIXME: self[index] = newValue
}
}
return
}
}
var j = [1,2,3,4,3,6,3,8,9]
var newArray = j.replaced(each: 3, with: 0)
I get a compile time error on the second method, replace(), at the line commented out with "//FIXME:" annotation. The compile time error says, "Ambiguous reference to member 'subscript'".
How can I fix the replace() code so it works?

Give this a shot
extension Array where Element: Equatable {
func replaced (each valueToReplace: Element, with newValue: Element) -> [Element] {
var newArray = [Element]()
newArray.reserveCapacity(self.count)
for element in self {
let newElement = (element == valueToReplace) ? newValue : element
newArray.append(newElement)
}
return newArray
}
mutating func replace(each valueToReplace: Element, with newValue: Element) {
for (i, element) in self.enumerated() {
if element == valueToReplace { self[i] = newValue }
}
}
}
var j = [1,2,3,4,3,6,3,8,9]
var newArray = j.replaced(each: 3, with: 0)
It would be better to remove the redundancy by just making replaced delegate to replace:
extension Array where Element: Equatable {
func replaced(each valueToReplace: Element, with newValue: Element) -> [Element] {
var copy = self
copy.replace(each: valueToReplace, with: newValue)
return copy
}
mutating func replace(each valueToReplace: Element, with newValue: Element) {
for (i, element) in self.enumerated() {
if element == valueToReplace { self[i] = newValue }
}
}
}

Related

Init a FloatingPoint from a string

I am trying to convert a 2d array of Strings into my custom generic type Matrix:
func convert(_ arr: [[String]]) -> Matrix<Element> {
var m: Matrix<Element> = Matrix()
for row in arr {
var v: [Element] = []
for e in row {
let convE: Element = Element(string: e) // right here I'd like to implement something like that: Element(string: e)
v.append(convE)
}
m.vectors.append(Vector(v))
}
return m
}
The Matrix.Element does conform to the FloatingPoint protocol. Please tell me if you wish to see the Matrix struct but I think I haven't implemented anything that's important for this question other than that the generic Element type of Matrix does conform to the FloatingPoint protocol.
My problem is I want Element to be something like Float, Double... (any of the FloatingPoint types) but how can I initialize a FloatingPoint from a string? I tried:
extension FloatingPoint {
init(string: String) {
self.init(Int(string)!)
}
}
which obviously only works for strings like "1", "2"... and not "1.2", "3.541" and so on which I want.
Edit:(#Leo Dabus)
protocol DArray: Sequence {
associatedtype Component: FloatingPoint
}
extension DArray {
static func * <T: DArray>(lhs: Self, rhs: T) -> Vector<Component> {
let v = lhs as? Vector<Component> ?? rhs as! Vector<Component>
let m = lhs as? Matrix<Component> ?? rhs as! Matrix<Component>
return Vector(m.map { zip(v, $0).map(*).reduce(0, +) })
}
static func / <T: DArray>(lhs: Self, rhs: T) -> Vector<Component> {
let v = lhs as? Vector<Component> ?? lhs as! Vector<Component>
let m = lhs as? Matrix<Component> ?? lhs as! Matrix<Component>
return Vector(m.map { zip(v, $0).map(/).reduce(0, +) })
}
}
struct Vector<Component: FloatingPoint>: DArray {
var components: [Component]
var count: Int {
return components.count
}
init(_ Components: [Component] = []) {
self.components = Components
}
subscript(i: Int) -> Component {
get {
return components[i]
} set {
components[i] = newValue
}
}
static func + (lhs: Self, rhs: Self) -> Self {
return Vector(zip(lhs, rhs).map(+))
}
static func - (lhs: Self, rhs: Self) -> Self {
return Vector(zip(lhs, rhs).map(-))
}
static func * (lhs: Self, rhs: Self) -> Self {
return Vector(zip(lhs, rhs).map(*))
}
static func / (lhs: Self, rhs: Self) -> Self {
return Vector(zip(lhs, rhs).map(/))
}
func empty(of length: Int) -> Self {
return Vector(Array(repeating: 0, count: length))
}
}
struct Matrix<Component: FloatingPoint>: DArray {
var vectors: [Vector<Component>]
var nRows: Int {
return vectors.count
}
var nColumns: Int {
guard !vectors.isEmpty else { return 0 }
return vectors[0].count
}
var count: Int {
return vectors.count
}
init(_ vectors: [Vector<Component>] = []) {
self.vectors = vectors
}
subscript(r: Int) -> Vector<Component> {
get {
return vectors[r]
}
set {
vectors[r] = newValue
}
}
subscript(r: Int, c: Int) -> Component {
get {
return vectors[r][c]
}
set {
vectors[r][c] = newValue
}
}
}
Additionally I have my two structs conform to the Sequence protocol.
(Note: I am the OP)
What I came up with now is:
extension FloatingPoint {
public init?(string: String) {
if Self.self == Double.self {
self = Double(string) as! Self
} else if Self.self == Float.self {
self = Float(string) as! Self
} else if Self.self == Float80.self {
self = Float80(string) as! Self
} else {
return nil
}
}
}
It works for my use case but I was wondering whether it is a good way of achieving what I am looking for. So I'd be happy for someone to evaluate my solution. (#Leo Dabus)
You can extend FloatingPoint protocol and constrain the generic type to LosslessStringConvertible:
extension StringProtocol {
func floatingPoint<T: FloatingPoint>() -> T? where T: LosslessStringConvertible {
T(String(self))
}
}
Note that CGFloat does NOT conform to LosslessStringConvertible so you would need to implement a custom String initializer:
extension CGFloat: LosslessStringConvertible {
private static let formatter = NumberFormatter()
public init?(_ description: String) {
guard let number = CGFloat.formatter.number(from: description) as? CGFloat else { return nil }
self = number
}
}
let double: Double? = "2.7".floatingPoint() // 2.7
let float: Float? = "2.7".floatingPoint() // 2.7
let float80: Float80? = "2.7".floatingPoint() // 2.7
let cgfloat: CGFloat? = "2.7".floatingPoint() // 2.7
There is already an initializer for FloatingPoint types but to make your code work you need to conform your Matrix Component to LosslessStringConvertible.
Can you try something like this:
extension FloatingPoint where Self == Double {
init(string: String) {
self.init(Double(string)!)
}
}
extension FloatingPoint where Self == Float {
init(string: String) {
self.init(Float(string)!)
}
}
this should work as well
extension FloatingPoint {
init(string: String) {
self.init(Self(string)!)
}
}

Swift Collection extension: pick every other item

I have written the following extension for Collection in Swift that returns a new Collection of every other element from a starting index.
extension Collection {
func everyOtherElement(from theIndex: Int = 0) -> [Element] {
if theIndex >= self.count { return self as! [Element] }
let start = self.index(startIndex, offsetBy: theIndex)
let end = self.endIndex
var everyOther = [Element]()
var iter = start
while iter != end {
everyOther.append(self[iter])
let next = index(after: iter)
if next == end { break }
iter = index(after: next)
}
return everyOther
}
}
There are probably ways to improve the code but my issue is when the Collection is a Dictionary. The extension works but returns an Array of Tuples [(key: key, value: value)]
I would like the extension to return a Dictionary.
I have tried Dictionary(uniqueKeysWithValuesMethod) which works fine once applied to the return of the everyOtherElement method but I can't seem to find a way to make it so directly.
var myDictionary = ["EN" : "Cheers", "SV" : "Skåll", "ES" : "Salud" ].everyOtherElement()
// returns [(key: "EN", value: "Cheers"),(key: "ES", value: "Salud")]
Dictionary(uniqueKeysWithValues: myDictionary.map { ($0.key, $0.value)})
// returns ["EN" : "Cheers", "ES" : "Salud" ]
Thanks for your help!
As other have mentioned a Dictionary is an unordered collection. If you would like to return a Dictionary you can simply extend dictionary and filter every other element. Note that there is no guarantee that the dictionary will keep the order that the key value pairs were enterer. That being said you can accomplish what you want as follow:
extension Dictionary {
var everyOtherElements: Dictionary {
var bool = true
return filter { _ in
defer { bool = !bool }
return bool
}
}
}
let dict = ["EN" : "Cheers", "SV" : "Skåll", "ES" : "Salud" ]
// returns [(key: "EN",
let everyOtherElements = dict.everyOtherElements // ["ES": "Salud", "SV": "Skåll"]
Regarding your comment
I understand from your reply that I can't extend all collection with
the same code, I need to break it down per type?
You don't need to extend every single element type, you can for instance extend RangeReplaceableCollection protocol and return Self which will englobe Strings as well:
extension RangeReplaceableCollection {
mutating func removeEvenIndexElements() {
var bool = true
removeAll { _ in
defer { bool = !bool }
return bool
}
}
mutating func removeOddIndexElements() {
var bool = false
removeAll { _ in
defer { bool = !bool }
return bool
}
}
func evenIndexElements() -> Self {
var bool = true
return filter { _ in
defer { bool = !bool }
return bool
}
}
func oddIndexElements() -> Self {
var bool = false
return filter { _ in
defer { bool = !bool }
return bool
}
}
}
var alphabet = "abcdefghijklmnopqrstuvwxyz"
alphabet.removeEvenIndexElements()
alphabet // "bdfhjlnprtvxz"
var arr = [1,2,3,4,5,6,7,8,9,0]
arr.removeOddIndexElements()
arr // [1, 3, 5, 7, 9]

swift4, general function : sequence(first:next:) issue - Out of bounds: index >= endIndex

I am learning Ray Wenderlich's LinkedList of Algorithm and data Structure
The code is OK:
let nodes = sequence(first: lhs.node) { $0?.next }
The code is not OK:
let nodes = sequence(first: lhs.node, next: { aNode -> Node<Value>? in
aNode?.next
})// The question is here
I want to know how to right the Swift gramma
To operator the LinkedList, the issue is here:
public struct LinkedList<Value> {
public var head: Node<Value>?
public var tail: Node<Value>?
public init() {}
public var isEmpty: Bool {
return head == nil
}
public mutating func push(_ value: Value) {
copyNodes()
head = Node(value: value, next: head)
if tail == nil {
tail = head
}
}
public mutating func append(_ value: Value) {
copyNodes()
guard !isEmpty else {
push(value)
return
}
tail!.next = Node(value: value)
tail = tail!.next
}
public func node(at index: Int) -> Node<Value>? {
var currentNode = head
var currentIndex = 0
while currentNode != nil && currentIndex < index {
currentNode = currentNode!.next
currentIndex += 1
}
return currentNode
}
private mutating func copyNodes() {
guard !isKnownUniquelyReferenced(&head) else {
return
}
guard var oldNode = head else {
return
}
head = Node(value: oldNode.value)
var newNode = head
while let nextOldNode = oldNode.next {
newNode!.next = Node(value: nextOldNode.value)
newNode = newNode!.next
oldNode = nextOldNode
}
tail = newNode
}
}
extension LinkedList: CustomStringConvertible {
public var description: String {
guard let head = head else {
return "Empty list"
}
return String(describing: head)
}
}
extension LinkedList: Collection {
public struct Index: Comparable {
public var node: Node<Value>?
static public func ==(lhs: Index, rhs: Index) -> Bool {
switch (lhs.node, rhs.node) {
case let (left?, right?):
return left.next === right.next
case (nil, nil):
return true
default:
return false
}
}
static public func <(lhs: Index, rhs: Index) -> Bool {
guard lhs != rhs else {
return false
}
var nodes = sequence(first: lhs.node) { $0?.next }
nodes = sequence(first: lhs.node, next: { (aNode) -> Node<Value>? in
aNode?.next
})// The question is here
// I overwrite the code to test it
return nodes.contains { $0 === rhs.node }
}
}
public var startIndex: Index {
return Index(node: head)
}
public var endIndex: Index {
return Index(node: tail?.next)
}
public func index(after i: Index) -> Index {
return Index(node: i.node?.next)
}
public subscript(position: Index) -> Value {
return position.node!.value
}
}
To Use the code:
example(of: "using collection") {
var list = LinkedList<Int>()
for i in 0...9 {
list.append(i)
}
print("Array containing last 3 elements: \(Array(list.suffix(3)))")
}
The LinkedList data structure
public class Node<Value> {
public var value: Value
public var next: Node?
public init(value: Value, next: Node? = nil) {
self.value = value
self.next = next
}
}
extension Node: CustomStringConvertible {
public var description: String {
guard let next = next else {
return "\(value)"
}
return "\(value) -> " + String(describing: next) + " "
}
}
Language sugar:
public func example(of description: String, action: () -> Void) {
print("---Example of \(description)---")
action()
print()
}
I checked apple's doc , https://developer.apple.com/documentation/swift/2015879-sequence
And have not found any nice idea.

Duplicating any type in a function in swift

so I made a func called duplicate that essentially takes any type and duplicates it however many times you want. It works flawlessly in swift playgrounds.
I am here to find out if there is a different/easier way to do what I am doing. The reason I ask is because I am taking the swift course on teamtreehouse.com. and supposedly this code does not work. So there must be a better way with less code or something to do the exact same thing I've done. Here is my code.
func duplicate<T>(_ item: T,_ numberOfItems: Int) -> Array<T> {
var items = numberOfItems
var newArray: [T] = []
while( items > 0){
newArray.append(item)
items = items - 1
}
return newArray
}
Array already has this built in, hard to get shorter than that:
let arr1 = [Int](repeating: 0, count: 1000)
let arr2 = [String](repeating: "hello", count: 20)
If you want some customization of the elements, use map:
let arr3 = (0..<10).map { i -> String in
return i % 2 == 0 ? "hello" : "world"
}
If you still insist on writing your own loop:
func duplicate<T>(_ item: T,_ numberOfItems: Int) -> [T] {
guard numberOfItems > 0 else { return [T]() }
var newArray = [T]()
for _ in 0..<numberOfItems {
newArray.append(item)
}
return newArray
}
Array init method
func duplicate<T>(_ item: T,_ numberOfItems: Int) -> [T] {
return [T](repeating: item, count: numberOfItems)
}
Range with map
func duplicate<T>(_ item: T,_ numberOfItems: Int) -> [T] {
return (0..<numberOfItems).map { _ in item }
}
Range with forEach and append
func duplicate<T>(_ item: T,_ numberOfItems: Int) -> [T] {
var newArray = [T]()
(0..<numberOfItems).forEach { _ in newArray.append(item) }
return newArray
}
While loop and append
func duplicate<T>(_ item: T,_ numberOfItems: Int) -> [T] {
var numberOfItems = numberOfItems
var newArray = [T]()
while(numberOfItems > 0) {
newArray.append(item)
numberOfItems -= 1
}
return newArray
}

Insertion-Order Dictionary (like Java's LinkedHashMap) in Swift?

Is there a standard swift class that is a Dictionary, but keeps keys in insertion-order like Java's LinkedHashMap? If not, how would one be implemented?
Didn't know of one and it was an interesting problem to solve (already put it in my standard library of stuff) Mostly it's just a matter of maintaining a dictionary and an array of the keys side-by-side. But standard operations like for (key, value) in od and for key in od.keys will iterate in insertion order rather than a semi random fashion.
// OrderedDictionary behaves like a Dictionary except that it maintains
// the insertion order of the keys, so iteration order matches insertion
// order.
struct OrderedDictionary<KeyType:Hashable, ValueType> {
private var _dictionary:Dictionary<KeyType, ValueType>
private var _keys:Array<KeyType>
init() {
_dictionary = [:]
_keys = []
}
init(minimumCapacity:Int) {
_dictionary = Dictionary<KeyType, ValueType>(minimumCapacity:minimumCapacity)
_keys = Array<KeyType>()
}
init(_ dictionary:Dictionary<KeyType, ValueType>) {
_dictionary = dictionary
_keys = map(dictionary.keys) { $0 }
}
subscript(key:KeyType) -> ValueType? {
get {
return _dictionary[key]
}
set {
if newValue == nil {
self.removeValueForKey(key)
}
else {
self.updateValue(newValue!, forKey: key)
}
}
}
mutating func updateValue(value:ValueType, forKey key:KeyType) -> ValueType? {
let oldValue = _dictionary.updateValue(value, forKey: key)
if oldValue == nil {
_keys.append(key)
}
return oldValue
}
mutating func removeValueForKey(key:KeyType) {
_keys = _keys.filter { $0 != key }
_dictionary.removeValueForKey(key)
}
mutating func removeAll(keepCapacity:Int) {
_keys = []
_dictionary = Dictionary<KeyType,ValueType>(minimumCapacity: keepCapacity)
}
var count: Int { get { return _dictionary.count } }
// keys isn't lazy evaluated because it's just an array anyway
var keys:[KeyType] { get { return _keys } }
// values is lazy evaluated because of the dictionary lookup and creating a new array
var values:GeneratorOf<ValueType> {
get {
var index = 0
return GeneratorOf<ValueType> {
if index >= self._keys.count {
return nil
}
else {
let key = self._keys[index]
index++
return self._dictionary[key]
}
}
}
}
}
extension OrderedDictionary : SequenceType {
func generate() -> GeneratorOf<(KeyType, ValueType)> {
var index = 0
return GeneratorOf<(KeyType, ValueType)> {
if index >= self._keys.count {
return nil
}
else {
let key = self._keys[index]
index++
return (key, self._dictionary[key]!)
}
}
}
}
func ==<Key: Equatable, Value: Equatable>(lhs: OrderedDictionary<Key, Value>, rhs: OrderedDictionary<Key, Value>) -> Bool {
return lhs._keys == rhs._keys && lhs._dictionary == rhs._dictionary
}
func !=<Key: Equatable, Value: Equatable>(lhs: OrderedDictionary<Key, Value>, rhs: OrderedDictionary<Key, Value>) -> Bool {
return lhs._keys != rhs._keys || lhs._dictionary != rhs._dictionary
}
Swift 5 version:
// OrderedDictionary behaves like a Dictionary except that it maintains
// the insertion order of the keys, so iteration order matches insertion
// order.
struct OrderedDictionary<KeyType: Hashable, ValueType> {
private var _dictionary: Dictionary<KeyType, ValueType>
private var _keys: Array<KeyType>
init() {
_dictionary = [:]
_keys = []
}
init(minimumCapacity: Int) {
_dictionary = Dictionary<KeyType, ValueType>(minimumCapacity: minimumCapacity)
_keys = Array<KeyType>()
}
init(_ dictionary: Dictionary<KeyType, ValueType>) {
_dictionary = dictionary
_keys = dictionary.keys.map { $0 }
}
subscript(key: KeyType) -> ValueType? {
get {
_dictionary[key]
}
set {
if newValue == nil {
self.removeValueForKey(key: key)
} else {
_ = self.updateValue(value: newValue!, forKey: key)
}
}
}
mutating func updateValue(value: ValueType, forKey key: KeyType) -> ValueType? {
let oldValue = _dictionary.updateValue(value, forKey: key)
if oldValue == nil {
_keys.append(key)
}
return oldValue
}
mutating func removeValueForKey(key: KeyType) {
_keys = _keys.filter {
$0 != key
}
_dictionary.removeValue(forKey: key)
}
mutating func removeAll(keepCapacity: Int) {
_keys = []
_dictionary = Dictionary<KeyType, ValueType>(minimumCapacity: keepCapacity)
}
var count: Int {
get {
_dictionary.count
}
}
// keys isn't lazy evaluated because it's just an array anyway
var keys: [KeyType] {
get {
_keys
}
}
var values: Array<ValueType> {
get {
_keys.map { _dictionary[$0]! }
}
}
static func ==<Key: Equatable, Value: Equatable>(lhs: OrderedDictionary<Key, Value>, rhs: OrderedDictionary<Key, Value>) -> Bool {
lhs._keys == rhs._keys && lhs._dictionary == rhs._dictionary
}
static func !=<Key: Equatable, Value: Equatable>(lhs: OrderedDictionary<Key, Value>, rhs: OrderedDictionary<Key, Value>) -> Bool {
lhs._keys != rhs._keys || lhs._dictionary != rhs._dictionary
}
}
extension OrderedDictionary: Sequence {
public func makeIterator() -> OrderedDictionaryIterator<KeyType, ValueType> {
OrderedDictionaryIterator<KeyType, ValueType>(sequence: _dictionary, keys: _keys, current: 0)
}
}
struct OrderedDictionaryIterator<KeyType: Hashable, ValueType>: IteratorProtocol {
let sequence: Dictionary<KeyType, ValueType>
let keys: Array<KeyType>
var current = 0
mutating func next() -> (KeyType, ValueType)? {
defer { current += 1 }
guard sequence.count > current else {
return nil
}
let key = keys[current]
guard let value = sequence[key] else {
return nil
}
return (key, value)
}
}
I didn't found way to make values 'lazy'.. need more research