Lin Du
Lin Du

Reputation: 102347

How to sort object of array with external condition and the property of object?

I am using lodash.orderBy method and try to sort data like this:

I have two external sort conditions: condition1 and condition2

const condition1 = 'aa';
const condition2 = 'b';

const datas = [
  { f1: 'aaa', f2: 'b', f3: '2019-01-01' },
  { f1: 'a', f2: 'b', f3: '2019-01-02' },
  { f1: 'a', f2: 'c', f3: '2019-01-08' },
  { f1: 'aa', f2: 'b', f3: '2019-01-08' },
  { f1: 'aa', f2: 'b', f3: '2019-01-09' },
  { f1: 'aa', f2: 'c', f3: '2019-01-07' },
  { f1: 'xxx', f2: 'c', f3: '2019-01-03' },
  { f1: 't', f2: 'd', f3: '2019-01-04' },
  { f1: 'a', f2: 'd', f3: '2019-01-01' },
  { f1: 'aa', f2: 'd', f3: '2019-01-02' },
];

I expect data sorted like this:

  const expect = [
          { f1: 'aa', f2: 'b', f3: '2019-01-09' },
          { f1: 'aa', f2: 'b', f3: '2019-01-08' },
          { f1: 'aa', f2: 'c', f3: '2019-01-07' },
          { f1: 'aa', f2: 'd', f3: '2019-01-02' },
          { f1: 'a', f2: 'b', f3: '2019-01-02' },
          { f1: 'aaa', f2: 'b', f3: '2019-01-01' },
          { f1: 'a', f2: 'c', f3: '2019-01-08' },
          { f1: 't', f2: 'd', f3: '2019-01-04' },
          { f1: 'xxx', f2: 'c', f3: '2019-01-03' },
          { f1: 'a', f2: 'd', f3: '2019-01-01' },
        ];

The sorting rule is:

  1. sort by f1 if the value of f1 equal with condition1 - priority 1
  2. sort by f2 if f1 is same, the value of f2 should equal with condition2 - priority 2
  3. sort by f3(desc) when f1 and f2 are same - priority 3

priority 1 is the highest.

Can't figure it out. Thanks for your help. lodash.orderBy and sort method of javascript, both of these solutions are ok.

Upvotes: 0

Views: 543

Answers (2)

Lin Du
Lin Du

Reputation: 102347

I found a solution but it looks like very verbose.

it('t1', () => {
        const goal = 'aa';
        const channelNme = 'b';

        const datas = [
          { goal: 'aaa', channelNme: 'b', date: '2019-01-01' },
          { goal: 'a', channelNme: 'b', date: '2019-01-02' },
          { goal: 'a', channelNme: 'c', date: '2019-01-08' },
          { goal: 'aa', channelNme: 'b', date: '2019-01-08' },
          { goal: 'aa', channelNme: 'b', date: '2019-01-09' },
          { goal: 'aa', channelNme: 'c', date: '2019-01-07' },
          { goal: 'xxx', channelNme: 'c', date: '2019-01-03' },
          { goal: 't', channelNme: 'd', date: '2019-01-04' },
          { goal: 'a', channelNme: 'd', date: '2019-01-01' },
          { goal: 'aa', channelNme: 'd', date: '2019-01-02' },
        ];

        const aa = datas.filter(d => d.goal === goal).sort(sortByDateDesc);
        const notAa = datas.filter(d => d.goal !== goal).sort(sortByDateDesc);
        const notAaB = notAa.filter(d => d.channelNme === channelNme).sort(sortByDateDesc);
        const notAaNotB = notAa.filter(d => d.channelNme !== channelNme).sort(sortByDateDesc);

        const actualValue = [...aa, ...notAaB, ...notAaNotB];

        function sortByDateDesc(a, b) {
          return new Date(b.date).getTime() - new Date(a.date).getTime();
        }

        const expectValue = [
          { goal: 'aa', channelNme: 'b', date: '2019-01-09' },
          { goal: 'aa', channelNme: 'b', date: '2019-01-08' },
          { goal: 'aa', channelNme: 'c', date: '2019-01-07' },
          { goal: 'aa', channelNme: 'd', date: '2019-01-02' },
          { goal: 'a', channelNme: 'b', date: '2019-01-02' },
          { goal: 'aaa', channelNme: 'b', date: '2019-01-01' },
          { goal: 'a', channelNme: 'c', date: '2019-01-08' },
          { goal: 't', channelNme: 'd', date: '2019-01-04' },
          { goal: 'xxx', channelNme: 'c', date: '2019-01-03' },
          { goal: 'a', channelNme: 'd', date: '2019-01-01' },
        ];
        console.log(`actualValue: ${JSON.stringify(actualValue, null, 2)}`);
        expect(actualValue).toEqual(expectValue);
      });

This unit test passed. Hope there is a better way.

Upvotes: 0

doberkofler
doberkofler

Reputation: 10361

I’m not sure I fully understand your problem, but it looks to me as if the JavaScript sort function combined with a custom sort function is all you need.

Something like this (not tested) code:

datas.sort(function(a, b) {
  if (a.f1 === condition1) {
    return a.f1.localeCompare(b.f1);
  } else if (a.f2 === condition2) {
    return a.f2.localeCompare(b.f2);
  } else {
    return a.f3.localeCompare(b.f3);
  }
});

Upvotes: 1

Related Questions