20855

[code]

    [("南口","19:00:00"),("北口","20:00:00"),("南口","22:40:00"),("北口","23:50:00")]
    
[/code]

となっている配列があり、

現在時刻を

[code]

    let now = NSDate()
    let formatter = NSDateFormatter()
    formatter.dateFormat = "HH:mm:ss"
    let string = formatter.stringFromDate(now)
    print(string)
    
[/code]

でとります。

その際に、タプルの中にある、現在時刻の次に来ると思われる指定時刻のindexを抽出したいのですが、いかんせんString型での大小比較ができなくて困っております。

`subStringWithRange`や`subStringToIndex`などで、Stringの一部分をとって、

toInt()でInt型に変更し、（NSDate（）でとった現在時刻も同時にtoInt型に変更して）大小比較を"HH"と"mm"で行って、index番号を抽出しようとしましたが、Int型に変えようとした時点でnilが表示されます。アンラップしてもダメみたいです。

NSDate型での比較を試みていますが、いまいちいい解決案が出ません。  
いい方法等があればご教授願えますでしょうか。

[補足]２４時以降の時刻に関してどうするのかという質問があったので補足させていただきます。  
配列要素の指定時刻については２４時以降は要素がない（存在しない）状態で考えております。


CC BY-SA 3.0
2016-01-12T06:17:58.683
20848
2016-01-14T05:11:02.957
2016-01-14T02:47:28.530
7362
12254
question
ios swift swift2
配列で抽出したStringと現在時刻を比較して、現在時刻に一番近い配列要素のindexを抽出したい


時刻の比較、差分の取得は、やはり`NSDate`インスタンスにして行うのが妥当と思います。  
文字列から、`NSDate`インスタンスを取得するには、メソッド`dateFromString()`を使います。  
`"19:00:00"`を引数にして取得すると、日付の情報がないので、`NSDate`の基準である2000年1月1日の日付になってしまいますが、時刻だけの比較なので問題はありません。（24時以降の時刻をどうするのか、お尋ねしたのはこれが理由です）  
`timeIntervalSinceDate()`による差分は、`NSTimeInterval`型（`Double`のTypeAlias）となり、容易に演算ができます。  
以下、Playgroundで実行できるサンプルコードです。実際に動かしてみてください。

[code]

    import Foundation
    
    // 時刻のフォーマットを作成。
    let timeFormatter = NSDateFormatter()
    timeFormatter.dateFormat = "HH:mm:ss"
    
    // 現在時刻から文字列を作成。
    let nowString = timeFormatter.stringFromDate(NSDate())
    // 文字列からNSDateインスタンスを作成。2000年1月1日＋現在時刻のインスタンスとなる。
    let nowTime = timeFormatter.dateFromString(nowString)!
    
    // ゲート名と時刻の配列。
    let gateArray: [(String, String)] = [("南口","19:00:00"),("北口","20:00:00"),("南口","21:40:00"),("北口","23:50:00")]
    // nowTimeとの差分を、別の配列に格納。
    // この箇所を修正。
    let intervalArray: [NSTimeInterval] = gateArray.map({(_, time) in
        // 時刻から、2000年1月1日＋時刻のNSDateインスタンスを作成。
        let diff = timeFormatter.dateFromString(time)
        // nowTimeとの差分の絶対値を返す。
        return abs(nowTime.timeIntervalSinceDate(diff ?? nowTime)) // 注
    })
    // 最小値（現在時刻にいちばん近い値）を検索。
    let minimumTime = intervalArray.minElement() ?? 0.0
    // 配列上のインデックスを取得。
    if let minIndex = intervalArray.indexOf(minimumTime) {
        print("The nearest gate is \(gateArray[minIndex].0). The time is \(gateArray[minIndex].1)")
    } else {
        print("Coudn't find any gate")
    }
    
[/code]

Optional型の処理で、ややヨレヨレしてしまいましたが、実践ではOptional Bindingを使って、安全なコードに仕上げたほうがいいでしょう。

* * *

注：Swiftは、C言語の標準ライブラリにある関数が、そのまま使えます。`import Darwin` or `import Foundation` or
`import UIKit`するのが条件です。`abs()`以外の関数例えば`sin()`、`sort()`なども使えます。

* * *

**Tuple** について

Tupleを関数（メソッド、クロージャ）の引数にとる時`(gate, time)`のような書式にします。サンプルコード中では`(_,
time)`となっていますが、第1要素の方は使用しないので、`_`で省略しています。このアンダーバーは、SwiftではTuple以外の場面でよく使われますので、覚えておくといいでしょう。


CC BY-SA 3.0
2016-01-12T09:07:33.130
20855
2016-01-14T05:11:02.957
2016-01-14T05:11:02.957
7362
7362
20848
answer