HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Getting the outliers of both dates and values

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
thevaluesoutliersdatesgettingbothand

Problem

This is working now, but it looks very inelegant. I'm sure there is a nicer way of doing this.

# Get the outliers of both the dates and values 
maxDate   = []
minDate   = []
maxVal    = []
minVal    = []
for k, v of series
  for d, i in v   
    series[k][i][1] = nearZero if d[1] is 0 
  series[k] = v = _.filter  v,    (d) -> not _.isNull d[1]      
  maxDate.push  _.max       v,    (d) -> d[0]
  minDate.push  _.min       v,    (d) -> d[0]
  maxVal .push  _.max       v,    (d) -> d[1]
  minVal .push  _.min       v,    (d) -> d[1]
maxDate   = _.max _.map maxDate,  (d) -> d[0]
minDate   = _.min _.map minDate,  (d) -> d[0]
maxVal    = _.max _.map maxVal,   (d) -> d[1]
minVal    = _.min _.map minVal,   (d) -> d[1]

Solution

Some notes:

-
I know many programmers like it, but this kind of perfectly aligned code looks pretty weird to me. Maybe my problem is that it's usually a sign that there is a repeated pattern that could be abstracted but has been prettified instead.

-
maxDate = []. Using imperative programming in JS/CS is very common, indeed, but I'd definitely take a functional approach when doing maths or logic (not that I know of any coding that does not deal with maths or logic ;-)).

-
(d) -> d[0]: Note that you can de-structure arrays: ([x, y]) -> x.

-
_.map maxDate, (d) -> d[0]. In my opinion list-comprehensions are more declarative than maps that use lambdas: (d[0] for d in maxDate).

-
Don't reuse variables: Those 4 accumulators hold two completely different structures in the course of the computation, that's not a good practice. Not even in imperative programming.

As I said, I'd write it in functional style, inmutable variables all the way through. It's a pity that CS has no real list-comprehensions and the results of nested loops must be flattened, but we'll have to live with it (_.flatten(xs, true) comes in handy as a one-level flattener). It would look something like this (you say you really need the modified series, so I'll use mash from my mixin):

nested_date_value_pairs =
  for key, pairs of series
    for [date, val] in pairs when val isnt null
      [date, if val is 0 then nearZero else val]
modified_series = _.mash(_.zip(_.keys(series), nested_date_value_pairs))      
dates_values = _.zip(_.flatten(nested_date_value_pairs, true)...)
[[minDate, maxDate], [minVal, maxVal]] = ([_.min(xs), _.max(xs)] for xs in dates_values)

Code Snippets

nested_date_value_pairs =
  for key, pairs of series
    for [date, val] in pairs when val isnt null
      [date, if val is 0 then nearZero else val]
modified_series = _.mash(_.zip(_.keys(series), nested_date_value_pairs))      
dates_values = _.zip(_.flatten(nested_date_value_pairs, true)...)
[[minDate, maxDate], [minVal, maxVal]] = ([_.min(xs), _.max(xs)] for xs in dates_values)

Context

StackExchange Code Review Q#28097, answer score: 4

Revisions (0)

No revisions yet.