1

関数を関数型に書き直そうとしています。機能が悪いのは承知しています。しかし、どうすれば var フィールドの使用を避けることができますwatermarkTimeか?

この関数は、タイムスタンプが連続的に増加する行に「1」を設定します。タイムスタンプが前の行のタイムスタンプよりも小さい場合は、日「2」を設定します。

case class Row(time: String, name: String, var day: Int)

val rows = List(new Row("09:18:52", "3_0711-082757_01001", 0),
                new Row("09:23:18", "3_0711-082757_01002", 0),
                new Row("09:33:43", "3_0711-082757_01004", 0),
                new Row("10:20:00", "3_0711-082757_01011", 0),
                new Row("05:03:38", "3_0711-082757_02001", 0),  // set secound day
                new Row("05:07:51", "3_0711-082757_02002", 0),
                new Row("05:13:02", "3_0711-082757_02003", 0),
                new Row("05:19:16", "3_0711-082757_02004", 0),
                new Row("10:54:27", "3_0711-082757_02015", 0),  // set first day 
                new Row("11:00:38", "3_0711-082757_02016", 0),
                new Row("11:07:28", "3_0711-082757_02017", 0))


def setDayFP(rows: List[Row]): List[Row] = {

  var watermarkTime = 0

  for (row <- rows) {

    val newTime = row.time.replaceAll(":","").toInt 

    if (watermarkTime < newTime) {
      watermarkTime = newTime
      row.day = 1
    }  else  {
      row.day = 2
    }
  }
  return rows 
}

結果は次のとおりです(日付と名前でソート):

Row(09:18:52,3_0711-082757_01001,1)
Row(09:23:18,3_0711-082757_01002,1)
Row(09:33:43,3_0711-082757_01004,1)
Row(10:20:00,3_0711-082757_01011,1)
Row(10:54:27,3_0711-082757_02015,1)
Row(11:00:38,3_0711-082757_02016,1)
Row(11:07:28,3_0711-082757_02017,1)
Row(05:03:38,3_0711-082757_02001,2)
Row(05:07:51,3_0711-082757_02002,2)
Row(05:13:02,3_0711-082757_02003,2)
Row(05:19:16,3_0711-082757_02004,2)

より良い解決策を探しています。前もって感謝します!

ポンゴ

4

5 に答える 5

2

楽しみのために:

case class Row(time: String, name: String, day: Int) {
  def timeAsInt = time.replaceAll(":", "").toInt
}

val rows = List(new Row("09:18:52", "3_0711-082757_01001", 0),
                new Row("09:23:18", "3_0711-082757_01002", 0),
                new Row("09:33:43", "3_0711-082757_01004", 0),
                new Row("10:20:00", "3_0711-082757_01011", 0),
                new Row("05:03:38", "3_0711-082757_02001", 0),  // set secound day
                new Row("05:07:51", "3_0711-082757_02002", 0),
                new Row("05:13:02", "3_0711-082757_02003", 0),
                new Row("05:19:16", "3_0711-082757_02004", 0),
                new Row("10:54:27", "3_0711-082757_02015", 0),  // set first day 
                new Row("11:00:38", "3_0711-082757_02016", 0),
                new Row("11:07:28", "3_0711-082757_02017", 0))


def setDayFP(rows: List[Row]): List[Row] = {
  lazy val rowStream:Stream[Row] = for((row, watermarkTime) <- rows.toStream.zip(watermarkStream)) yield
    row.copy(day = if(watermarkTime < row.timeAsInt) 1 else 2) 


  lazy val watermarkStream:Stream[Int] = 0 #:: rowStream.zip(watermarkStream).map{ case (row, watermarkTime) =>
    math.max(watermarkTime, row.timeAsInt)
  }

  rowStream.toList
}

setDayFP(rows)
于 2012-07-19T16:03:59.317 に答える
1

少し試してみましたfoldLeftが、ここに行く方法ではないと思います。これが私の解決策です:

def sdfp(rows: List[Row]): List[Row] = {
  var watermark = 0
  rows.map(row => {
    val time = row.time.replaceAll(":","").toInt
    if(watermark < time) {
      watermark = time
      row.day = 1
    } else {
      row.day = 2
    }
    row
  }
}

map関数を取り、それをコレクションのすべての要素に適用します。

編集

この問題を解決する別の方法を見つけました:

def sdfp2(rows: List[Row]): List[Row] = {
  var watermark = 0
  for {
    row <- rows
    val time = row.time.replaceAll(":","").toInt
    val after = watermark < time
  } yield {
    if(after) { watermark = row; row.day = 1 } else row.day = 2
    row
  }
}
于 2012-07-19T15:18:33.077 に答える