0

I'm struggling with sorting two levels. The logic is as follows. If any of the objects have a status, return the most recent object with a status. If none of the objects have a status, return the most recent object without a status.

var apps = [
  { status: 'PASS', 
    date_created: Thu Sep 03 2015 17:24:45 GMT-0700 (PDT)
  },
  { status: 'FAIL',
    date_created: Thu Sep 02 2015 17:24:45 GMT-0700 (PDT),
  },
  { status: '',
    date_created: Thu Sep 03 2015 17:24:45 GMT-0700 (PDT),
  }
]

var desired_result = [{ status: 'PASS', 
    date_created: Thu Sep 03 2015 17:24:45 GMT-0700 (PDT)
  }]

var apps_2 = [
  { status: '', 
    date_created: Thu Sep 03 2015 17:24:45 GMT-0700 (PDT)
  },
  { status: '',
    date_created: Thu Sep 02 2015 17:24:45 GMT-0700 (PDT),
  },
  { status: '',
    date_created: Thu Sep 01 2015 17:24:45 GMT-0700 (PDT),
  }
]

var desired_resul2 = [{ status: '', 
    date_created: Thu Sep 03 2015 17:24:45 GMT-0700 (PDT)
  }]

I've tried

var sorted = _.sort_by(apps, function (x) { x.date_updated });

I've also looked a few other SO questions but can't keep the objects in place after the first sort.

Community
  • 1
  • 1
user2954587
  • 4,661
  • 6
  • 43
  • 101

2 Answers2

2

If I understand your question correctly, here is what you are looking for. http://jsfiddle.net/whxu5sea/3/

You need to filter the elements to ensure they have a status of ANY kind. Then sort them by date, earliest first. Then get that first value. In my example I assumed the dates where strings, but still should work.

var apps = [
  { status: 'PASS', 
    date_created: 'Thu Sep 03 2015 17:24:45 GMT-0700 (PDT)'
  },
  { status: 'FAIL',
    date_created: 'Thu Sep 02 2015 17:24:45 GMT-0700 (PDT)',
  },
  { status: '',
    date_created: 'Thu Sep 01 2015 17:24:45 GMT-0700 (PDT)',
  }
];

var x;
var arr = _.filter(apps, function(data) {
    return !!data.status.length;
});

x = _.chain( arr.length ? arr : apps )
    .sortBy(function(data) {
        return new Date(data.date_created).getTime();
    }).last().value();

console.log( x );

To check if it works when no status is provided: http://jsfiddle.net/whxu5sea/4/

I hope this helps. LMK if any further clarification is needed.

EDIT: Updated to get NEWEST element (last).

sic1
  • 486
  • 3
  • 8
1

Here is a simple solution that iterates just once through apps, without a filtering step. See here for a jsfiddle.

The concept is that, if status is falsy, its date is converted into a negative number that retains the correct sort order among all falsy elements, but makes all falsy elements have a lower sort order than all non-falsy ones.

We convert the falsy element dates by subtracting 8640000000000001, which is (the maximimum millis in a Date, plus one).

var x = _.chain(apps).sortBy(function(x) {
      var date = new Date(x.date_created).getTime();
      return x.status ? date : date - 8640000000000001;
    }).last().value();

console.log( x );
Community
  • 1
  • 1
cybersam
  • 63,203
  • 6
  • 53
  • 76