Keyの配列とDictionaryを見比べて、配列になくてDictionaryにある値を削除する

タイトルが長く、わかりにくいです:cop:

# つまり何がしたいの？
ここにStringの配列があります。

```swift
let keys = ["A", "B", "C", "D"]
```
Dictionaryもあります。

```swift
var dictionary = ["A": 0, "B": 1, "C": 2, "D": 3, "E": 4]
```
見比べると、`"E"`というkeyが、`keys `にはなくて`dictionary`にはあります。
この`"E"`を削除したい:muscle:

# どちらにもあるものを取得
`dictionary`のkeyを取得して、`keys`に含まれるかを確認する。
`keys`に含まれるものだけの配列を取得できた

```swift
let keys = ["A", "B", "C", "D"]
var dictionary = ["A": 0, "B": 1, "C": 2, "D": 3, "E": 4]
let contains = dictionary.keys.filter { (key) -> Bool in
	keys.contains(key)
}
print(contains) // ["B", "A", "C", "D"]
```

# Dictionaryにしかないものを取得
先ほどの判定を逆にしたら良い。
`dictionary`にしか含まれないものの配列を取得できた

```swift
let nocontains = dictionary.keys.filter { (key) -> Bool in
	!keys.contains(key) // !をつける
}
print(nocontains) // ["E"]
```

# Dictionaryにしかないものを削除
あとは`dictionary`から削除するだけ。

```swift
nocontains.forEach { (removeKey) in
	dictionary.removeValue(forKey: removeKey)
}
print(dictionary) // ["B": 1, "A": 0, "C": 2, "D": 3]
```

# Dictionaryを拡張
ついでに、`keys`に含まれるものを削除する関数も作成

```swift
extension Dictionary {
	
	// 引数の配列に含まれていないものを削除
	// mutating func removeUnincludedValue(in keys: Array<Key>) {
	// 	self.keys.filter { (key) -> Bool in
	// 		!keys.contains(key)
	// 		}.forEach { (removeKey) in
	// 			self.removeValue(forKey: removeKey)
	// 	}
	// }
	
	// 追記: コメント欄で教えてもらった
	func removeUnincludedValue(in keys: Array<Key>) -> Dictionary<Key, Value> {
		return self.filter { keys.contains($0.key) }
	}
	
	// 追記: コメント欄で教えてもらった
	func filtered(byKeys keys: Array<Key>) -> Dictionary {
		
		var newDictionary: Dictionary = [:]
		var keysIterator = keys.makeIterator()
		
		newDictionary.reserveCapacity(self.count)
		
		while let key = keysIterator.next() {
			if let value = self[key] {
				newDictionary[key] = value
			}
		}
		
		return newDictionary
		
	}
	
	// 追記: コメント欄で教えてもらった
	mutating func filter(byKeys keys: [Key]) {
		
		self = self.filtered(byKeys: keys)
		
	}
	
	// 追記: コメント欄で教えてもらった
	// func filtered(keys: [Key]) -> Dictionary {
	// 	return keys.reduce(into: [Key: Value]()) { dict, key in dict[key] = self[key] }
	// }

	// 追記: コメント欄で教えてもらったのを、swiftっぽく書いてみた
	func filtered(keys: [Key]) -> Dictionary {
		return keys.reduce(into: [Key: Value]()) { $0[$1] = self[$1] }
	}



	// 引数の配列に含まれているものを削除
	// mutating func removeIncludedValue(in keys: Array<Key>) {
	// 	self.keys.filter { (key) -> Bool in
	// 		keys.contains(key)
	// 	}.forEach { (removeKey) in
	// 		self.removeValue(forKey: removeKey)
	// 	}
	// }

	// 追記: もっと簡単に書けた
	mutating func removeIncludedValue(in keys: Array<Key>) {
		keys.forEach { (removeKey) in
			self.removeValue(forKey: removeKey)
		}
	}
}
```
## `keys`に含まれてないけど、`dictionary`に含まれているものを削除

```swift
let keys = ["A", "B", "C", "D"]
var dictionary = ["A": 0, "B": 1, "C": 2, "D": 3, "E": 4]
dictionary.removeUnincludedValue(in: keys) // ["B": 1, "A": 0, "C": 2, "D": 3]
```

## `keys`に含まれていて、`dictionary`にも含まれているものを削除

```swift
let keys = ["A", "B", "C", "D"]
var dictionary = ["A": 0, "B": 1, "C": 2, "D": 3, "E": 4]
dictionary.removeIncludedValue(in: keys) // ["E": 4]
```

## 型が違う時はコンパイルエラーでるから安心

```swift
let keys = ["A", "B", "C", "D"]
var dictionary1 = [0: 0, 1: 1, 2: 2]
dictionary1.removeUnincludedValue(in: keys)
// cannot convert value of type '[String]' to expected argument type 'Array<Int>'
```
「`dictionary1`のkeyはIntなので`keys`はIntの配列でください」ということですね

# 最後に
ふと思ってやってみたが、簡単に作ることができました。
もっと簡単にできるとか、なにか間違いがありましたら教えてください
あと、関数のネーミングに不安が残りました:ok_hand: