配列内の要素をキーワードで検索する[swift]

#はじめに
テキスト等を配列内に入れておく際に、キーワードで検索を行いそのキーワードを含む要素を取り出せたら便利だなと思ったので実装してみました。完成形は↓　キーワードはスペースを入れることで区切り、複数のキーワードでの検索ができます。
<img width="375" alt="Simulator Screen Shot 2016.04.28 22.10.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/95928/e8662bb6-c2a9-9da0-5b83-f0767aa9a9d9.png">
<img width="375" alt="Simulator Screen Shot 2016.04.29 9.24.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/95928/3622f5bf-99ac-0f00-170a-001a76eda8e2.png">


#Interface Builder
textFieldを置き、ボダンを三種類（add,　search,　clear）を用意しました。下部にはtableviewを置き、配列内の要素及び検索結果を表示させます。こんな感じ。<img width="1280" alt="スクリーンショット 2016-04-29 9.20.21.png" src="https://qiita-image-store.s3.amazonaws.com/0/95928/a893149c-9404-3e93-6b8f-5542f822af76.png">


#実装
スペースで区切られた文字列を分けて取得します。Extensionを頭に加えます。

```lang:ViewController

import UIKit

// keyword分解用のextension
extension String {
    var words: [String] {
        return componentsSeparatedByCharactersInSet(.punctuationCharacterSet()).joinWithSeparator("").componentsSeparatedByString(" ").filter{!$0.isEmpty}
    }
}

```

stringArrayには予めテキストを入れておきます。

```lang:ViewController
 //すべてのテキストを入れる配列
    var stringArray = ["this is a testString, please add your sentence.","I like apples", "Do you like apples?","今日はいい天気ですね", "はい、いい天気です","私はappleが好きです"]
    //検索結果を入れる配列
    var searchArray = [String]()
    @IBOutlet var table: UITableView!
    @IBOutlet var textField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        table.delegate = self
        table.dataSource = self
        table.reloadData()
    }


```

###ボタン
add、search、clearのボタンの実装を行います。addはテキストを追加するボタン、searchは検索を行うボタン、clearはリセットするボタンです。

```lang:ViewController
    //addボタン
    @IBAction func add(sender: UIButton) {
        if textField?.text == "" {
            textAlert()
        } else {
            let newText = textField.text
            stringArray.append(newText!)
            print("全テキスト->",stringArray)
            table.reloadData()
        }
    }
    
    //searchボタン
    @IBAction func search(sender: UIButton) {
        if textField?.text == "" {
            textAlert()
        } else {
            let keyWords = textField.text?.words
            var preSearchArray = [String]()
            print(keyWords)
            
            for keyWord in keyWords! {
                // keyWordを含むテキストをresultsに加える
                let results = stringArray.filter{$0.containsString(keyWord)}
                for result in results {
                preSearchArray.append(result)
                    
                //重複する配列は除く
                let removeOverlapResultArray = NSOrderedSet(array: preSearchArray)
                searchArray = removeOverlapResultArray.array as! [String]
                }
                print("検索結果を入れる配列 ->",searchArray)
                
                //もしキーワードに引っかかる検索が見つからなかった場合アラートを出す
                if searchArray == [] {
                    let alert = UIAlertView()
                    alert.title = "アラート"
                    alert.message = "検索されたキーワードを含むテキストは存在しません"
                    alert.addButtonWithTitle("OK")
                    alert.show()
                }
                table.reloadData()
            }
        }
    }
    
    //clearボタン
    @IBAction func clear (sender: UIButton) {
        searchArray = []
        textField.text?.removeAll()
        table.reloadData()
    }
    
    func textAlert() {
        let alert = UIAlertView()
        alert.title = "アラート"
        alert.message = "文字が入力されていません"
        alert.addButtonWithTitle("OK")
        alert.show()
    }

```
こんな感じ。filterがめちゃくちゃ便利ですね・・・重複する配列を除かないと、検索キーワードを複数持つテキストは重複して表示されてしまいます。

###tableview
あとはtableviewの実装部分です。通常のテキストを表示する場合と検索結果を表示する場合に留意して・・・

```ViewController
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if searchArray == [] {
            return stringArray.count
        } else {
            return searchArray.count
        }
    }
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell: UITableViewCell =  UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "cell")
        if searchArray == [] {
            cell.textLabel?.text = stringArray[indexPath.row]
        } else {
            cell.textLabel?.text = searchArray[indexPath.row]
        }
        return cell
    }
    
```

#終わりに
複数のキーワード（例えばapple, 天気）で検索を行う場合、**appleか天気をどちらかを含む検索結果**が表示されます。appleかつ天気、両方を含む検索を行う場合にはどうしたらいいのでしょうか・・・

コード、拙い点が多いかと思います。是非アドバイス等いただけたら幸いです。

#参考
[スペースで区切られた文字列の取得](http://stackoverflow.com/questions/29667419/how-can-i-remove-or-replace-all-punctuation-characters-from-a-string)
[filterの使い方](http://stackoverflow.com/questions/34511918/swift-2-filter-array-of-strings-including-like-condition)
[配列内で重複する要素を除去する](http://qiita.com/ariiyu/items/55d08bfae02e586d6ff8)