概要
383. Ransom Noteを解いているときに書いた処理をもしかしたらどこかで使うかも?と思ったので記事として残しておきます。
詳細
以下のようなケースで使用できます。
ransomNoteとmagazineの2つの文字列が与えられたとき、ransomNoteがmagazineの文字を使って構成できる場合はtrueを、そうでない場合はfalseを返す。
magazineの各文字はransomNoteで一度しか使用できない。
今回書いた方法はDictionary
を用いた処理、そしてreduce
関数を用いた処理です。
まずはDictionaryを用いた例です。
こちらは単純な考え方で、Dictionary内にmagazine
の内容を詰め込んだ後にransomNote
内との照会を行う、という内容になります。
基本的なデータ構造を用いている分、記述がしやすい反面、個人的にはちょっと記述量が多く、やや冗長に感じます。
class Solution {
// ransomNoteの文字列がmagazine文字列のみで構成されているかを確認する関数
func canConstruct(_ ransomNote: String, _ magazine: String) -> Bool {
var counter = [Character: Int]()
// Dictionaryのcounter内に`magazine`の内容を詰める処理
for m in magazine{
if let count = counter[m]{
counter[m] = count+1
}else{
counter[m] = 1
}
}
// ransomNote内とDictionaryのcounter内の照合を行い、存在していて、かつカウントが0よりも大きい場合にはカウントの減算を行い、処理を継続する
for r in ransomNote{
if let count = counter[r],count > 0{
counter[r] = count-1
}else{
return false
}
}
return true
}
}
次にreduce関数を用いた例です。
こちらも基本的な考え方は先述の内容と同じですが、reduce
関数を用いた処理を関数として外出ししており、メイン処理を行う関数がスッキリしています。
コードの量がスッキリし、読みやすくなった印象です。
class Solution {
// ransomNoteの文字列がmagazine文字列のみで構成されているかを確認する関数
func canConstruct(_ ransomNote: String, _ magazine: String) -> Bool {
var magazineWordCount = countCharacters(magazine)
for r in ransomNote {
if let count = magazineWordCount[r],count > 0{
magazineWordCount[r] = count - 1
}else{
return false
}
}
return true
}
// reduce関数を用いて関数内に存在する文字とその文字が登場する回数をカウントする関数
func countCharacters(_ str:String) -> [Character:Int]{
return str.reduce(into: [:]) { counts,char in
counts[char,default:0] += 1
}
}
}
ただ、このようなコードを書いておいてなんですが、私のSwiftの習熟度的には何も見ずにいきなりreduce
関数を使った処理を書いてと言われると困ると思ったので、記事として残しておきます!