-1

I understand well how the compare function works thanks to this thread How does sort function work in JavaScript, along with compare function

but I am wondering how it can be used with complex data such as the following:

Let's say I have the following data.

var data = [{
  id: _A2, 
  parent: {
    parent_id: _A1 
  },
  createdOn: 1.1
},{
  id:_A4, 
  parent: null ,
  createdOn: 1.1
},{
  id: _A1, 
  parent: null ,
  createdOn: 1
},{
  id: _A3, 
  parent: {
    parent_id: _A1 
  },
  createdOn: 1.2
},{
  id: _A5, 
  parent: {
    parent_id: _A4 
  },
  createdOn: 1.2
}]

I want to sort it first by creation date, and then group children with their parents which gives us:

var data = [{
  id: _A1, 
  parent: null ,
  createdOn: 1
},{
  id: _A2, 
  parent: {
    parent_id: 1 
  },
  createdOn: 1.1
},{
  id: _A3, 
  parent: {
    parent_id: 1 
  },
  createdOn: 1.2
},{
  id: _A4, 
  parent: null ,
  createdOn: 1.1
},{
  id: _A5, 
  parent: {
    parent_id: _A4 
  },
  createdOn: 1.2
}]

Is it even possible with the sort function?

Community
  • 1
  • 1
v1r00z
  • 796
  • 11
  • 18
  • This makes no sense. You say you want to order by creation date, but then you want _A3 before _A4? – Oriol Jul 09 '16 at 00:49
  • @Oriol Why it does not make sens, maybe you need to learn more about the sort before down voting my question! – v1r00z Jul 22 '16 at 23:36
  • Check my solution out https://jsfiddle.net/crazyvirus/np2pjctg/ – v1r00z Jul 22 '16 at 23:43
  • It makes no sense because `1.1 < 1.2`, so _A4 should go before _A3. Not sure what sort you want, but that's not "sort it first by creation date". – Oriol Jul 22 '16 at 23:45
  • lets try to give it more sens.. Lets say you have a flat json of comments mixed with children comments or replies like the example above.. I want to display parent comment along with their children sorted by creation date.. It does not matter if the child creation date is greater than other parents, it should be under its parent -- children will eventually be sorted in asc direction. – v1r00z Jul 22 '16 at 23:51
  • Please kindly remove the down vote! – v1r00z Jul 22 '16 at 23:58
  • I still insist to remove your down vote @Oriol – v1r00z Oct 09 '16 at 22:24
  • I still insist your question makes no sense because `1.1 < 1.2`, so _A4 should go before _A3. Not sure what sort you want, but that's not "sort it first by creation date". – Oriol Oct 09 '16 at 22:38
  • You could tell me kindly to edit my question and put more info... rather than down voting! I bet the JSFiddle that I've done can be useful for many people. – v1r00z Oct 09 '16 at 23:12

3 Answers3

0

The second answer of the same post explains pretty well about comparing a specific property in an array of objects:

https://stackoverflow.com/a/6568093/4809052

For example, if want to compare the create date, you can do

var sortedArray = myArray.sort(function(a,b){
                                  return (a.createdOn - b.createdOn);
                              });

Or if you want to compare by id, you can compare each character in the string _A1.

Community
  • 1
  • 1
  • Thanks for you quick reply, but it does not answer my question. Here a jsfiddle about what I want to achieve : https://jsfiddle.net/ofpu6f0v/4/ – v1r00z Jul 09 '16 at 00:19
0

I believe this does what you are asking. To answer your question in short, sorting alone cannot manage it.

data.sort(function(rec1, rec2) {
    return rec1.createdOn - rec2.createdOn;
});

var grouped = [];
data.forEach(function(record) {
    if (!record.parent) {
        grouped.push(record);
        data.forEach(function(child) {
            if (child.parent) {
                if (child.parent.parent_id == record.id) grouped.push(child);
            }
        });
    }
});

data = grouped;
0

Update Here a solution that I came with :

var data = [{
  id: '_A2',
  color: '#00ff00',
  parent: {
    parent_id: '_A1'
  },
  created: 1.1
}, {
  id: '_A4',
  color: '#bf1616',
  parent: null,
  created: 1.1
}, {
  id: '_A1',
  parent: null,
  color: '#469649',
  created: 1
}, {
  id: '_A3',
  color: '#00ff00',
  parent: {
    created: 1, 
    parent_id: '_A1'
  },
  created: 1.2
}, {
  id: '_A5',
  color: '#f62222',
  parent: {
    created: 1.1,
    parent_id: '_A4'
  },
  created: 1.2
},{
  id: '_A6',
  color: '#00ff00',
  parent: {
    created: 1, 
    parent_id: '_A1'
  },
  created: 11
},{
  id: '_A8',
  color: 'yellow',
  parent: {
    created: 0.5, 
    parent_id: '_A1'
  },
  created: 0.6
},{
  id: '_A7',
  color: '#c2c22b',
  parent: null,
  created: 0.5
}],
    ct = document.getElementById("unordered-data"),
    result = document.getElementById("result"),
    createRow = function (row) {
      var child = document.createElement('div');
      child.innerHTML = '<span class="row" style="background-color:' + row['color'] + '">' + row['id'] +  ' -- ' + row['created'] + '</span>';
      return child

    },


    compareFn = function (lhs, rhs) {
      return (lhs > rhs) ? 1 : (lhs < rhs ? -1 : 0);
    },

    compareSelfOrParentCreated = function (record1, record2) {
      var parent1 = record1.parent,
          parent2 = record2.parent;

      return compareFn(
        parent1 ? parent1.created : record1.created,
        parent2 ? parent2.created : record2.created
      );

    },
    compareSelfOrParentId = function (record1, record2) {
      var parentId1 = record1.parent,
          parentId2 = record2.parent;
      return compareFn(!!parentId1 ? parentId1.id : record1.id,
                       !!parentId2 ? parentId2.id : record2.id);
    },

    idPropertyOrEmptyString = function (obj) {
      return (!!obj && !!obj.id) ? obj.id : '';
    };

for (row in data) {
  ct.appendChild(createRow(data[row]));
}

for(r in data){
  data[r]._id =  idPropertyOrEmptyString(data[r].parent);
}

data.sort(function(r1, r2){
  var cmpCreated = compareSelfOrParentCreated(r1, r2); 
  if(cmpCreated === 0){
    var cmpParent = compareSelfOrParentId(r1, r2);
    if(cmpParent === 0){
      var parentAsc = compareFn(r1._id, r2._id);
      if(parentAsc === 0){
       return compareFn(r1.created, r2.created);
      } else{
        return parentAsc;
      }
    } else {
      return cmpParent
    }
  } else{
    return cmpCreated;
  }
});

for (row in data) {
  result.appendChild(createRow(data[row]));
}
.row {
  display:block;
  width:200px;
  padding:10px;
}
<h2>
 Unordered data
</h2>
<div id="unordered-data">
</div>

<h2>
Result
</h2>

<div id="result">

</div>
v1r00z
  • 796
  • 11
  • 18