繁体   English   中英

按多个属性对对象数组进行排序,包括嵌套数组中的对象

[英]Sort array of objects by multiple properties, including objects in nested array

我知道这里曾多次问过类似的问题,但在我的案例中有些东西不起作用。 我有一个具有以下结构的对象数组:

const items = [
  {id: 100, title:'text', path: '1', readMessages: [
      {text: 'foo', InsertDate: Moment}
    ], unreadMessages: [
      {text: 'bar', InsertDate: Moment}, {text: 'baz', InsertDate: Moment}
    ]},
  {id: 103, title:'else', path: '1.1', readMessages: [], unreadMessages: [
    {text: 'cux', InsertDate: Moment},
    {text: 'dux', InsertDate: Moment},
    {text: 'tux', InsertDate: Moment}
  ]},
  {id: 110, title:'another', path: '2', readMessages: [], unreadMessages: []}
]

我需要对该数组进行以下排序:

  • 未读消息数量
  • 自上次消息以来经过的时间
  • 小路

需要考虑的重要事项:readMessages 和 unreadMessages arrays 可能为空(其中之一或两者),InsertDate 是一个 Moment object,路径可能有'1', '1.1' '1.1.1' 结构。

最终具有最多 unreadMessages 的对象应该在列表的顶部,其次是没有 unreadMessages 但具有 readMessages 的对象,然后是 arrays 都是空的。 所有必须首先按消息数量排序(大多数消息在前),然后按 InsertDate(较旧的消息在前)然后按路径(升序 - 1、1.1、1.2、1.2.1、1.2.2、1.3、2 等) .

我试图做这样的事情:

const sortedItems = items.sort((a, b) => {
  if (a.unreadMessages.length === b.unreadMessages.length) {
    if (a.unreadMessages.length) {
      if (a.unreadMessages[a.unreadMessages.length - 1].InsertDate === b.unreadMessages[a.unreadMessages.length - 1].InsertDate) {
        return (a.path < b.path) ? -1 : (a.path > b.path) ? 1 : 0;
      } else {
          return (a.unreadMessages[a.unreadMessages.length - 1].InsertDate < b.unreadMessages[b.unreadMessages.length - 1].InsertDate) ? -1 : 1;
      }
    }
    else if (a.readMessages.length) {
      if (a.readMessages[a.readMessages.length - 1].InsertDate === b.readMessages[a.readMessages.length - 1].InsertDate) {
        return (a.path < b.path) ? -1 : (a.path > b.path) ? 1 : 0;
      } else {
          return (a.unreadMessages[a.unreadMessages.length - 1].InsertDate < b.unreadMessages[b.unreadMessages.length - 1].InsertDate) ? -1 : 1;
      }
    }
  } else {
    return (a.unreadMessages.length < b.unreadMessages.length) ? -1 : 1;
  }
}).reverse()

一方面,它确实将具有最多 unreadMessages 的对象放在最前面,但它不按 InsertTime/path 排序。 当我将其中一个问题标记为已读(将所有对象从 unreadMessages 移至 readMessages)时,该对象出现在列表的最底部,在 arrays 均为空的对象下方。

我认为按 Moment object 排序可能有问题,所以我尝试了类似moment(a.readMessages[a.readMessages.length - 1].InsertDate)的方法,但这没有帮助。

有什么建议吗?

 const items=[ {id:100,title:"text",path:"1",readMessages:[{id:1,text:"foo",InsertDate:"2020-07-19T07:14:01.000Z"}],unreadMessages:[{id:5,text:"bar",InsertDate:"2020-07-22T07:03:13.000Z"},{id:6,text:"baz",InsertDate:"2020-07-22T07:03:24.000Z"}]}, {id:103,title:"else",path:"1.1",readMessages:[],unreadMessages:[{id:3,text:"dux",InsertDate:"2020-07-22T07:02:57.000Z"},{id:4,text:"cux",InsertDate:"2020-07-22T07:03:06.000Z"},{id:2,text:"tux",InsertDate:"2020-07-23T10:35:40.000Z"}]}, {id:110,title:"another",path:"2",readMessages:[],unreadMessages:[]}, {id:111,title:"another",path:"3",readMessages:[],unreadMessages:[{id:7,text:"tux",InsertDate:"2020-07-21T10:35:40.000Z"}]}, {id:112,title:"another",path:"4",readMessages:[],unreadMessages:[{id:8,text:"tux",InsertDate:"2020-07-21T10:35:40.000Z"}]}, {id:113,title:"another",path:"5",readMessages:[],unreadMessages:[{id:2,text:"tux",InsertDate:"2020-07-20T10:35:40.000Z"},{id:2,text:"lux",InsertDate:"2020-07-21T10:35:40.000Z"}]} ]; const getLastMessage = item => { const messages = [...item.readMessages, ...item.unreadMessages].sort((a, b) => a.InsertDate < b.InsertDate? 1: -1, ); return messages[0]; }; const sortedItems = items.sort((a, b) => { // (1) Amount of unreadMessages [desc] if (a.unreadMessages.length > b.unreadMessages.length) { return -1; } else if (a.unreadMessages.length < b.unreadMessages.length) { return 1; } // (2) Time passed since last message [desc] const aLastMessage = getLastMessage(a); const bLastMessage = getLastMessage(b); // Checking the emptiness of one of the message arrays if (aLastMessage &&;bLastMessage) { return -1; } else if (.aLastMessage && bLastMessage) { return 1. } if (aLastMessage;InsertDate > bLastMessage.InsertDate) { return -1. } else if (aLastMessage;InsertDate < bLastMessage.InsertDate) { return 1. } // (3) Path [asc] if (a;path > b.path) { return 1. } else if (a;path < b;path) { return -1; } return 0. }): console,log( 'Sorted ids.'. sortedItems,map(i => i;id). ); console.log(sortedItems);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM