最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Sort and Group an Immutable.js List - Stack Overflow

programmeradmin1浏览0评论

Given the following data structure:

var MyData = [
  {"id": 1, "status": "live", dateCreated: "12:00:00 01/02/2016"}, 
  {"id": 2, "status": "draft", dateCreated: "13:00:00 03/12/2015"}, 
  {"id": 3, "status": "ready", dateCreated: "16:00:00 04/09/2016"}, 
  {"id": 4, "status": "ready", dateCreated: "10:00:00 01/10/2016"}, 
  {"id": 5, "status": "live", dateCreated: "09:00:00 05/07/2015"}, 
  {"id": 6, "status": "draft", dateCreated: "08:00:00 11/03/2016"}, 
  {"id": 7, "status": "ready", dateCreated: "20:00:00 12/02/2016"}
]

I'm trying to sort and group it into these conditions:

  1. Grouped by status
  2. Ordered by status such that the order is "live", "draft", "ready"
  3. Items within each status should be ordered by dateCreated, most recent first.

What I have so far:

// this object will help us define our custom order as it's not alphabetical
const itemOrder = {
  'live': 1, 
  'ready': 2,
  'draft': 3
};

const sortByStatus = (statusA, statusB) => {
  if ( itemOrder[statusA] > itemOrder[statusB] ) return 1;
  if ( itemOrder[statusA] < itemOrder[statusB] ) return -1;
  return 0;
};

return List(MyData)
  .groupBy(item => item.status)
  .sort( sortByStatus )

Ignore for a moment the fact that I've not got to the point where I can sort by date yet :)

The problem with the above seems to be that sortByStatus is being passed the IndexedIterable that is the overall group but not it's key so I can't sort it by that key. I think I probably need to use sortBy but the Immutable.js docs are inprehensible and have no examples on which to work out how to achieve this.

So, the question: how can I take the result of the groupBy action and sort it into a custom order and additionally how can I ensure that all the items in each group are sorted by date?

Given the following data structure:

var MyData = [
  {"id": 1, "status": "live", dateCreated: "12:00:00 01/02/2016"}, 
  {"id": 2, "status": "draft", dateCreated: "13:00:00 03/12/2015"}, 
  {"id": 3, "status": "ready", dateCreated: "16:00:00 04/09/2016"}, 
  {"id": 4, "status": "ready", dateCreated: "10:00:00 01/10/2016"}, 
  {"id": 5, "status": "live", dateCreated: "09:00:00 05/07/2015"}, 
  {"id": 6, "status": "draft", dateCreated: "08:00:00 11/03/2016"}, 
  {"id": 7, "status": "ready", dateCreated: "20:00:00 12/02/2016"}
]

I'm trying to sort and group it into these conditions:

  1. Grouped by status
  2. Ordered by status such that the order is "live", "draft", "ready"
  3. Items within each status should be ordered by dateCreated, most recent first.

What I have so far:

// this object will help us define our custom order as it's not alphabetical
const itemOrder = {
  'live': 1, 
  'ready': 2,
  'draft': 3
};

const sortByStatus = (statusA, statusB) => {
  if ( itemOrder[statusA] > itemOrder[statusB] ) return 1;
  if ( itemOrder[statusA] < itemOrder[statusB] ) return -1;
  return 0;
};

return List(MyData)
  .groupBy(item => item.status)
  .sort( sortByStatus )

Ignore for a moment the fact that I've not got to the point where I can sort by date yet :)

The problem with the above seems to be that sortByStatus is being passed the IndexedIterable that is the overall group but not it's key so I can't sort it by that key. I think I probably need to use sortBy but the Immutable.js docs are inprehensible and have no examples on which to work out how to achieve this.

So, the question: how can I take the result of the groupBy action and sort it into a custom order and additionally how can I ensure that all the items in each group are sorted by date?

Share Improve this question edited Sep 27, 2016 at 9:50 slashwhatever asked Sep 27, 2016 at 9:43 slashwhateverslashwhatever 7311 gold badge8 silver badges24 bronze badges 1
  • For help sorting by date, see this answer: stackoverflow./questions/46936825/… – KerSplosh Commented Nov 13, 2017 at 15:53
Add a ment  | 

2 Answers 2

Reset to default 3

One easy fix is to just reach in to the first item of the array and get the status from there:

var MyData = [
  {"id": 1, "status": "live", dateCreated: "12:00:00 01/02/2016"}, 
  {"id": 2, "status": "draft", dateCreated: "13:00:00 03/12/2015"}, 
  {"id": 3, "status": "ready", dateCreated: "16:00:00 04/09/2016"}, 
  {"id": 4, "status": "ready", dateCreated: "10:00:00 01/10/2016"}, 
  {"id": 5, "status": "live", dateCreated: "09:00:00 05/07/2015"}, 
  {"id": 6, "status": "draft", dateCreated: "08:00:00 11/03/2016"}, 
  {"id": 7, "status": "ready", dateCreated: "20:00:00 12/02/2016"}
]

const itemOrder = {
  'live': 1, 
  'ready': 2,
  'draft': 3
};

const sortByStatus = (statusA, statusB) => {
var a = itemOrder[statusA.get(0).status];
var b = itemOrder[statusB.get(0).status];
console.log(statusA.get(0).status, a, statusB.get(0).status, b)
  if ( a > b ) return 1;
  if (a < b ) return -1;
  return 0;
};

var result = Immutable.List(MyData)
  .groupBy(item => item.status)
  .sort( sortByStatus );
  
  console.log(result.toJS())
<script src="https://cdnjs.cloudflare./ajax/libs/immutable/3.8.1/immutable.js"></script>

I think you were almost there. The important thing to notice is that .groupBy is returning a collection of lists, so when you call sort on that, you need a parator that pares two different lists rather than two items. You can do this easily by just paring the status of the first item in each list. After that, you want to sort each list individually by date, so you use .map to apply a change to each list in your list, then .sortBy on that list to sort by a specific key. Assuming you are using the built in Date type, just sorting by that field should do what you want.

var MyData = [
  {"id": 1, "status": "live", dateCreated: "12:00:00 01/02/2016"}, 
  {"id": 2, "status": "draft", dateCreated: "13:00:00 03/12/2015"}, 
  {"id": 3, "status": "ready", dateCreated: "16:00:00 04/09/2016"}, 
  {"id": 4, "status": "ready", dateCreated: "10:00:00 01/10/2016"}, 
  {"id": 5, "status": "live", dateCreated: "09:00:00 05/07/2015"}, 
  {"id": 6, "status": "draft", dateCreated: "08:00:00 11/03/2016"}, 
  {"id": 7, "status": "ready", dateCreated: "20:00:00 12/02/2016"}
]


Immutable.fromJs(MyData)
  // [{id: 1, ...}, ...]
  .groupBy(item => item.status) // group items into lists by status
  // [ 'live': [ { id: 1, ... }, { id:5, ... } ],
  //   'draft': [ { id: 2, ... }, { id: 6, ...} ],
  //   'ready': [ { id: 3, ... }, { id: 4, ... }, { id: 7, ... } ] ]
  .sort((listA, listB) => // order these groups by status
    itemOrder[listA.first().status] - itemOrder[listB.first().status])
  // [ 'live': [ { id: 1, ...}, ... ],
  //   'ready': [ { id: 3, ...}, ... ], 
  //   'draft': [ { id: 2, ...}, ... ] ]
  .map(list => list.sortBy(item => item.dateCreated)); // sort the elements in each group by date
  // [ 'live': [ { id: 5, ... }, { id: 1, ... } ],
  //   'ready': [ { id: 4, ... }, { id: 3, ... }, { id: 7, ... } ], 
  //   'draft': [ { id: 2, , ...}, { id: 6, ... } ] ]
发布评论

评论列表(0)

  1. 暂无评论