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
Related
I have a BinarySearchTree protocol and want to make all implementations of it to conform to Sequence protocol. Since the traverse method is enough for iteration, I wanted to provide a default implementation for makeIterator method which is required by Sequence so that any implementation of BinarySearchTree becomes iterable without doing anything further. But compiler gives two errors:
Type 'BinarySearchTreeImp' does not conform to protocol 'BinarySearchTree'
Type 'BinarySearchTreeImp' does not conform to protocol 'Sequence'
I have done a similar thing for LinkedList and it worked fine.
What is wrong here?
protocol BinarySearchTree: Sequence where Element == (Key, Value) {
associatedtype Key: Comparable
associatedtype Value
func insert(key: Key, value: Value)
func remove(key: Key) -> Value?
func find(key: Key) -> Value?
func findPredecessor(key: Key) -> (Key, Value)?
func findSuccessor(key: Key) -> (Key, Value)?
func min() -> (Key, Value)?
func max() -> (Key, Value)?
func removeMin() -> (Key, Value)?
func removeMax() -> (Key, Value)?
func traverse() -> AnySequence<(Key, Value)>
}
extension BinarySearchTree {
func makeIterator() -> AnyIterator<(Self.Key, Self.Value)> {
return traverse().makeIterator()
}
}
fileprivate class BSTNode<Key:Comparable, Value> {
let key: Key
let value: Value
var left: BSTNode<Key, Value>?
var right: BSTNode<Key, Value>?
unowned var parent: BSTNode<Key, Value>?
var isLeaf: Bool {
left == nil && right == nil
}
init(key: Key, value: Value){
self.key = key
self.value = value
}
func toTuple() -> (Key, Value) {
return (self.key, self.value)
}
func min() -> BSTNode {
guard let left = left else { return self }
return left.min()
}
func max() -> BSTNode {
guard let right = right else { return self }
return right.max()
}
func find(key: Key) -> BSTNode? {
if key == self.key {
return self
}
if key < self.key {
guard let left = left else { return nil }
return left.find(key: key)
}
guard let right = right else { return nil }
return right.find(key: key)
}
func findPredecessor() -> BSTNode? {
if let left = left { return left.max() }
var current = self
while let parent = current.parent {
if current === parent.right {
return parent
}
current = parent
}
return nil
}
func findSuccessor() -> BSTNode? {
if let right = right { return right.min() }
var current = self
while let parent = current.parent {
if current === parent.left {
return parent
}
current = parent
}
return nil
}
func insert(key: Key, value: Value) -> BSTNode {
if key <= self.key {
if let left = left {
return left.insert(key: key, value: value)
} else {
left = BSTNode(key: key, value: value)
left!.parent = self
return left!
}
} else {
if let right = right {
return right.insert(key: key, value: value)
} else {
right = BSTNode(key: key, value: value)
right!.parent = self
return right!
}
}
}
func delete() {
if isLeaf {
promoteChild(nil)
return
}
if left == nil {
promoteChild(right)
right = nil
return
}
if right == nil {
promoteChild(left)
left = nil
return
}
let successor = right!.min()
assert(successor.parent != nil)
successor.left = left
if successor.parent === self {
promoteChild(successor)
} else {
let successorsParent = successor.parent!
promoteChild(successor)
// successor must be left child unless it is right child of self
successorsParent.left = nil
successor.max().right = self.right
}
left = nil
right = nil
}
private func promoteChild(_ child: BSTNode?) {
guard let parent = parent else { return }
child?.parent = parent
if parent.left === self {
parent.left = child
} else {
parent.right = child
}
self.parent = nil
}
}
class BinarySearchTreeImp<Key: Comparable, Value> : BinarySearchTree {
private var root: BSTNode<Key, Value>?
init(){}
func min() -> (Key, Value)? {
return root?.min().toTuple()
}
func max() -> (Key, Value)? {
return root?.max().toTuple()
}
func find(key: Key) -> Value? {
return root?.find(key: key)?.value
}
func findPredecessor(key: Key) -> (Key, Value)? {
return root?.find(key: key)?.findPredecessor()?.toTuple()
}
func findSuccessor(key: Key) -> (Key, Value)? {
return root?.find(key: key)?.findSuccessor()?.toTuple()
}
func insert(key: Key, value: Value) {
if let root = root {
root.insert(key: key, value: value)
} else {
root = BSTNode(key: key, value: value)
}
}
func remove(key: Key) -> Value? {
guard let node = root?.find(key: key) else { return nil }
let result = node.value
node.delete()
return result
}
func removeMin() -> (Key, Value)? {
guard let node = root?.min() else {
return nil
}
node.delete()
return node.toTuple()
}
func removeMax() -> (Key, Value)? {
guard let node = root?.max() else {
return nil
}
node.delete()
return node.toTuple()
}
func traverse() -> AnySequence<(Key, Value)> {
return AnySequence { () -> AnyIterator<(Key, Value)> in
var currentNode: BSTNode<Key, Value>? = self.root?.min()
return AnyIterator {
let result = currentNode?.toTuple()
currentNode = currentNode?.findSuccessor()
return result
}
}
}
}
The problem comes from the min()/max() requirements:
func min() -> (Key, Value)?
func max() -> (Key, Value)?
If you comment them out, the code builds.
Sequence also exposes these two functions, however they are part of an extension available only if Element is Comparable, which is not your case, so not sure why it confuses the compiler.
Another workaround is to have BinarySearchTreeImp declare the Iterator typealias:
typealias Iterator = AnyIterator<(Key, Value)>
, this will also silence the compiler, however it's not clear for future conformances that this will need to be added to solve a semi-obscure compiler error message.
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]
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.
I am currently in need of a performant bidirectional map. In Swift, a dictionary can be reversed, however, that will return a tuple of the types it is made of, not a counterpart dictionary.
Is there a library for that or does someone have ideas on how to address this issue?
Thanks
With Swift 4 you could easily make your own using a generic struct:
struct BidiMap<F:Hashable,T:Hashable>
{
private var _forward : [F:T]? = nil
private var _backward : [T:F]? = nil
var forward:[F:T]
{
mutating get
{
_forward = _forward ?? [F:T](uniqueKeysWithValues:_backward?.map{($1,$0)} ?? [] )
return _forward!
}
set { _forward = newValue; _backward = nil }
}
var backward:[T:F]
{
mutating get
{
_backward = _backward ?? [T:F](uniqueKeysWithValues:_forward?.map{($1,$0)} ?? [] )
return _backward!
}
set { _backward = newValue; _forward = nil }
}
init(_ dict:[F:T] = [:])
{ forward = dict }
init(_ values:[(F,T)])
{ forward = [F:T](uniqueKeysWithValues:values) }
subscript(_ key:T) -> F?
{ mutating get { return backward[key] } set{ backward[key] = newValue } }
subscript(_ key:F) -> T?
{ mutating get { return forward[key] } set{ forward[key] = newValue } }
subscript(to key:T) -> F?
{ mutating get { return backward[key] } set{ backward[key] = newValue } }
subscript(from key:F) -> T?
{ mutating get { return forward[key] } set{ forward[key] = newValue } }
var count:Int { return _forward?.count ?? _backward?.count ?? 0 }
}
var bd = BidiMap( [1:"A", 2:"B", 3:"C"] )
bd[1] // "A"
bd["B"] // 2
bd[4] = "D"
bd[to:"D"] // 4
bd[from:4] // "D"
var int2int = BidiMap( [1:2, 5:3] )
int2int[from:1] // 2
int2int[to:3] // 5
[EDIT] improved performance a bit by delaying rebuilding of mirror dictionary until it is actually referenced.
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 }
}
}
}