1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-02-08

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

つまり何がしたいの?

ここにStringの配列があります。

let keys = ["A", "B", "C", "D"]

Dictionaryもあります。

var dictionary = ["A": 0, "B": 1, "C": 2, "D": 3, "E": 4]

見比べると、"E"というkeyが、keys にはなくてdictionaryにはあります。
この"E"を削除したい:muscle:

どちらにもあるものを取得

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

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にしか含まれないものの配列を取得できた

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

Dictionaryにしかないものを削除

あとはdictionaryから削除するだけ。

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

Dictionaryを拡張

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

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に含まれているものを削除

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にも含まれているものを削除

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

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

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:

1
1
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?