2016-05-31 17 views
4

は、私は開始時刻と終了時刻をタプルのリストを持っていると言う:Funtional方法の開始時刻と終了時刻との

List((1,10), (2,11), (3,11), (13,14)) 

だけ緩和はその開始時間が

を昇順されています

私は次の出力を期待:

List((0,1), (11,13)) 

手続きの実装が機能して非常に簡単です、しかし、私は(慣用的に)これを行うための手掛かりを持っていないでしょう。

スケーラ・フォー・イールド・ループは、結果が入力と同じサイズになるため、不適切なフィットに見えます。縮小/折りたたみでは、答えとしてタプルが1つしかないという制限があります。

list 
    .foldLeft((List[(Int,Int)](), 0)) { 
    case ((res, se), (s, e)) => 
     if(s>se) ((se, s)::res,e) 
     else (res, e) 
    } 
    ._1 
    .reverse 

説明:

+0

整数で作業していますか?または、少なくとも離散的な値のセットで? – meucaa

+0

実際の問題はyesです。これらはUNIXタイムスタンプです。 – hbogert

+0

ライブラリやアルゴリズムの説明をお探しですか?関連性があります:https://github.com/rklaehn/intervalset –

答えて

4

は、次の解決策を考えてみましょう。空の間隔のリスト(最初は空、List(Int、Int))と最後の間隔の終わり(最初は0)の値のペアを累積します。各ステップで現在の間隔(s、e)をとり、最後の間隔の終わりと比較します。最後の最後よりも大きい現在の間隔の開始は、ギャップがあり、我々はその結果にそれを取る場合:(se, s)::res

+0

私は折り畳みの可能性を過小評価しました。これは美しいですが、私の手続き的な解決法に似ていますが、結局私はそれほど遠く離れていませんでした。 – hbogert

0

あなたはスキャンたちの間にフィルタやマップ

list.scanLeft((0,0,0))((l,r) => 
    if(r._1 > l._3) {(l._2, r._1, r._2)} 
    else {(l._1,r._2, r._2)}) 
filter(x => x._2 != x._3) 
map(x => (x._1, x._2)) 

scanLeftの組み合わせを使用することができますスキャンペアの右側の要素、つまりジョブを参照して、これまでの終了時間((0,0,0)トリプレットで開始されている)よりも大きいかどうかを確認します。もしそうなら、私たちの出力順に含むトリプレット、ギャップ

  • ギャップ
  • ギャップを終了したジョブの停止時間の終わりの

    1. スタート。

    右手の、つまり仕事の開始時間が左手の終了時間よりも大きくない場合、空白の隙間はなく、現在のジョブストリークを拡大するトリプレットを作成します2.

  • として

  • 同じ

    1. コピー
    2. コピージョブストリークの開始時間最後のジョブの終了時間によって、より良い用語)、現在識別することができますトリプレットの2番目と3番目の要素が異なることを確認することでギャップを埋めることができます(これはiff-relationです)。今我々はこの事実をフィルタリングする。最後に適切な出力形式を得るためにマップを作成します。

  • 関連する問題