Nine3KiD
Nine3KiD

Reputation: 713

How to make Lodash orderBy to sort only the records with data?

I have an array with below elements,

let stats = [
  { 'keyword': 'testing',                'searches': 0,    'isAnalysed': false },
  { 'keyword': 'testing software',       'searches': 235,  'isAnalysed': true },
  { 'keyword': 'the testing',            'searches': 0,    'isAnalysed': false },
  { 'keyword': 'testing the boundries',  'searches': 0,    'isAnalysed': false },
  { 'keyword': 'testing business ideas', 'searches': 155,  'isAnalysed': true },
  { 'keyword': 'testing electronics',    'searches': 0,    'isAnalysed': false },
  { 'keyword': 'testing and assessment', 'searches': 0,    'isAnalysed': false },
  { 'keyword': 'testing microservices',  'searches': 65,   'isAnalysed': true },
];

And I want to sort the array to look like this,

Ascending order;

let stats = [
  { 'keyword': 'testing microservices',  'searches': 65,   'isAnalysed': true },
  { 'keyword': 'testing business ideas', 'searches': 155,  'isAnalysed': true },
  { 'keyword': 'testing software',       'searches': 235,  'isAnalysed': true },
  { 'keyword': 'testing',                'searches': 0,    'isAnalysed': false },
  { 'keyword': 'the testing',            'searches': 0,    'isAnalysed': false },
  { 'keyword': 'testing the boundries',  'searches': 0,    'isAnalysed': false },
  { 'keyword': 'testing electronics',    'searches': 0,    'isAnalysed': false },
  { 'keyword': 'testing and assessment', 'searches': 0,    'isAnalysed': false },
];

Descending order;

let stats = [
  { 'keyword': 'testing software',        'searches': 235,  'isAnalysed': true },
  { 'keyword': 'testing business ideas',  'searches': 155,  'isAnalysed': true },
  { 'keyword': 'testing microservices',   'searches': 65,   'isAnalysed': true },
  { 'keyword': 'testing',                 'searches': 0,    'isAnalysed': false },
  { 'keyword': 'the testing',             'searches': 0,    'isAnalysed': false },
  { 'keyword': 'testing the boundries',   'searches': 0,    'isAnalysed': false },
  { 'keyword': 'testing electronics',     'searches': 0,    'isAnalysed': false },
  { 'keyword': 'testing and assessment',  'searches': 0,    'isAnalysed': false },
];

Yes, I want to sort by the searches if that object isAnalysed = true. I'm using Lodash orderBy(). Here is the sorting code segment I wrote for this.

  // direction - asc/desc
  const sortedData = _.orderBy(stats, [function (object) {
    if (object.isAnalysed === true) return object.searches;
  }], [direction]);

But this sorts the entire array like a normal sort which is done by the searches. What am I missing here?

Upvotes: 0

Views: 326

Answers (3)

Nine3KiD
Nine3KiD

Reputation: 713

I found the method to work with by these two suggested answers. First I break the data set into two parts based on analysed and not analysed. Then I sort the analysed data set and concatenate that with the not analysed data set.

  const statsAnalysed = data.filter((object) => object.isAnalysed);
  const statsNotAnalysed = data.filter((object) => !object.isAnalysed);

  const sortedData = _.orderBy(statsAnalysed, [element], [direction]).concat(statsNotAnalysed);

Upvotes: 0

Matt
Matt

Reputation: 74791

orderBy isAnalysed first.

orderBy(stats, ['isAnalysed', 'searches'], ['desc', 'desc']))
orderBy(stats, ['isAnalysed', 'searches'], ['desc', 'asc']))

Regular Array#sort compare functions.

function compareAsc(a, b){
  if (a.isAnalysed === false && b.isAnalysed === false) return 0
  if (a.isAnalysed === false && b.isAnalysed === true) return 1
  if (a.isAnalysed === true && b.isAnalysed === false) return -1  
  return a.searches - b.searches
}
function compareDesc(a, b){
  if (a.isAnalysed === false && b.isAnalysed === false) return 0
  if (a.isAnalysed === false && b.isAnalysed === true) return 1
  if (a.isAnalysed === true && b.isAnalysed === false) return -1    
  return b.searches - a.searches
}
stats.sort(compareAsc)
stats.sort(compareDesc)

Upvotes: 1

Christian
Christian

Reputation: 7852

If you don't have to use lodash something like this should solve it:

const stats = [
  { 'keyword': 'testing software',        'searches': 235,  'isAnalysed': true },
  { 'keyword': 'testing business ideas',  'searches': 155,  'isAnalysed': true },
  { 'keyword': 'testing microservices',   'searches': 65,   'isAnalysed': true },
  { 'keyword': 'testing',                 'searches': 0,    'isAnalysed': false },
  { 'keyword': 'the testing',             'searches': 0,    'isAnalysed': false },
  { 'keyword': 'testing the boundries',   'searches': 0,    'isAnalysed': false },
  { 'keyword': 'testing electronics',     'searches': 0,    'isAnalysed': false },
  { 'keyword': 'testing and assessment',  'searches': 0,    'isAnalysed': false },
];
const statsAnalysed = stats.filter(stat => stat.isAnalysed);
const statsNotAnalysed = stats.filter(stat => !stat.isAnalysed);

const statsAnalysedSorted = (order) => statsAnalysed.sort((s1, s2) => order === 'asc' ? s1.searches - s2.searches : s2.searches - s1.searches);

console.log(statsAnalysedSorted('asc').concat(statsNotAnalysed));

Upvotes: 1

Related Questions