Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Series.firstValue .lastValue #11

Closed
dwhjames opened this issue May 30, 2014 · 1 comment
Closed

Series.firstValue .lastValue #11

dwhjames opened this issue May 30, 2014 · 1 comment

Comments

@dwhjames
Copy link
Contributor

Series has the following methods:

def firstValue: Option[(K, V)] = {
  var i = 0
  while (i < index.size) {
    val row = index.indexAt(i)
    if (column.isValueAt(row))
      return Some(index.keyAt(i) -> column.valueAt(row))
    i += 1
  }
  None
}

def lastValue: Option[(K, V)] = {
  var i = index.size - 1
  while (i >= 0) {
    val row = index.indexAt(i)
    if (column.isValueAt(row))
      return Some(index.keyAt(i) -> column.valueAt(row))
    i -= 1
  }
  None
}

These are currently only used in one place:

def getFirstAndLastTopLevelMetricData(settings: ScaleSettings): EitherT[Future, MetricDataError, (List[Metric], Frame[Company, MetricColumn])] = {
  import MetricColumn.{ date, comparable }

  getTopLevelMetricData(settings) map { case (metadata, frame0) =>
    val metricKey = MetricColumn.Data(settings.metricsString(0))
    val frame = frame0.mapRowGroups { case (comp, group0) =>
      val group = group0.columns(date).groupAs[LocalDate]
      val values = group.column[Number](metricKey)
      val stripped = for {
        (date0, _) <- values.firstValue
        (date1, _) <- values.lastValue
      } yield {
        group.retainRows(date0, date1).columns(comparable).groupAs[Company]
      }
      stripped getOrElse Frame.empty[Company, MetricColumn]
    }

    (metadata, frame)
  }
}

My issue here is that these behave quite differently to the First and Last reducers.

  1. they return keys as well as values
  2. they ignore NM

We could add a new method to Series:

def findAsc[B](f: (K, Column[V], Int) => Option[B]): Option[B] = {
  var i = 0
  while (i < index.size) {
    val row = index.indexAt(i)
    val res = f(index.keyAt(i), column, row)
    if (res.isDefined)
      return res
    i += 1
  }
  None
}

Then firstValue becomes equivalent to:

def findFirstValue: Option[(K, V)] =
  findAsc((key, col, row) =>
    if (column.isValueAt(row))
      Some(key -> column.valueAt(row))
    else
      None
  )

Similarly, we would have findDesc and findLastKeyVal.

I guess there is a penalty for abstracting these traversals to findAsc and findDesc.

Thoughts?

@dwhjames
Copy link
Contributor Author

dwhjames commented Jul 8, 2014

Addressed in #16

@dwhjames dwhjames closed this as completed Jul 8, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant