如何在javascript中对嵌套的对象数组进行排序?

Posted

技术标签:

【中文标题】如何在javascript中对嵌套的对象数组进行排序?【英文标题】:How to sort a nested array of objects in javascript? 【发布时间】:2019-09-30 00:21:26 【问题描述】:

我有一个对象数组:

entities: [
  
    name: "zBroomsticks PTY",
    id: 34098365,
    entityType: "personal",
    facilities: [
      
        type: "Home loan",
        account: "032654 987465",
        existing: true,
        modified: "04/12/2018",
        limit: 100000
      ,
      
        type: "Credt card",
        account: "032654 987465",
        existing: false,
        modified: "04/12/2018",
        limit: 200000
      ,
      
        type: "Credt card",
        account: "032654 987465",
        existing: false,
        modified: "04/12/2018",
        limit: 10000
      ,
      
        type: "Credt card",
        account: "032654 987465",
        existing: false,
        modified: "04/12/2018",
        limit: 10000
      
    ]
  ,
  
    name: "Mr John Doe -3409865, Mrs Jane Doe -34098365",
    id: 34098365,
    entityType: "business",
    facilities: [
      
        type: "Overdraft",
        account: "032654 987465",
        existing: false,
        modified: "04/12/2018" ,
        limit: 10000
      
    ]
  ,
  
    name: "Mr Jack",
    id: 34098365,
    entityType: "mixed",
    facilities: [
      
        type: "Overdraft",
        account: "032654 987465",
        existing: false,
        modified: "04/12/2018",
        limit: 10000
      
    ]
  
]

我想按特定顺序排序:

    entity.name:按字母升序排列。

    entity.entityType: 1. 个人 2. 商务 3. 混合

    entity.facilities.limit:降序

这是我目前得到的代码:

sortData(entities) 
    var order = 
      entityType:  personal: 2, business: 1 
    ;

    return entities.map(ent =>
      entities.sort(
        (a, b) =>
          a.name - b.name ||
          order.entityType[a.facilities.entityType] - order.entityType[b.facilities.entityType]
      )
    );

我知道如何执行名称排序,但找不到 2 和 3 的方法?

Link to code

【问题讨论】:

limit 只是为了对facilities 数组进行排序,还是你希望它也会影响到外部数组entities 只是设施数组。 【参考方案1】:

首先,要通过names 订购,您可以使用localeCompare()。其次,facilities 数组中没有属性 entityType,但您正在尝试访问它。现在,一种解决方案是首先使用Array.map() 来获取一个新数组,其中facilities 数组按limit 属性排序,然后您可以将map() 返回的新数组首先按names 排序,然后再排序通过entityType 属性,如下所示:

const input = [name:"zBroomsticks PTY",id:34098365,entityType:"personal",facilities:[type:"Home loan",account:"032654 987465",existing:true,modified:"04/12/2018",limit:100000,type:"Credt card",account:"032654 987465",existing:false,modified:"04/12/2018",limit:200000,type:"Credt card",account:"032654 987465",existing:false,modified:"04/12/2018",limit:10000,type:"Credt card",account:"032654 987465",existing:false,modified:"04/12/2018",limit:10000],name:"Mr John Doe -3409865, Mrs Jane Doe -34098365",id:34098365,entityType:"business",facilities:[type:"Overdraft",account:"032654 987465",existing:false,modified:"04/12/2018",limit:10000],name:"Mr Jack",id:34098365,entityType:"mixed",facilities:[type:"Overdraft",account:"032654 987465",existing:false,modified:"04/12/2018",limit:10000],name:"Mr Jack",id:34098365,entityType:"personal",facilities:[type:"Overdraft",account:"032654 987465",existing:false,modified:"04/12/2018",limit:10000]];

let order = 
  entityType: personal:1, business:2, mixed:3
;

function sortData(entities)
    
    let limitOrder = entities.map(e =>
    
        e.facilities.sort((a, b) => b.limit - a.limit);
        return e;
    );

    return limitOrder.sort((a, b) =>
    
        return a.name.localeCompare(b.name) ||
               order.entityType[a.entityType] - order.entityType[b.entityType];
    );


console.log(sortData(input));
.as-console background-color:black !important; color:lime;
.as-console-wrapper max-height:100% !important; top:0;

注意,我使用不同的entityType 复制了与name: "Mr Jack" 相关的对象,因此您可以看到当有两个等于names 的对象时算法的执行情况。

【讨论】:

【参考方案2】:

按照12 和最后3 的优先顺序对数组进行排序

2 条件,您可以使用index 对象来映射entityType 及其权重。

3 因为要按descending order 排序,所以在facilities 列表中找到最小的limit 值并与其他项进行比较。

let entities = [
  
    name: "zBroomsticks PTY",
    id: 34098365,
    entityType: "personal",
    facilities: [
      
        type: "Home loan",
        account: "032654 987465",
        existing: true,
        modified: "04/12/2018",
        limit: 100000
      ,
      
        type: "Credt card",
        account: "032654 987465",
        existing: false,
        modified: "04/12/2018",
        limit: 200000
      ,
      
        type: "Credt card",
        account: "032654 987465",
        existing: false,
        modified: "04/12/2018",
        limit: 10000
      ,
      
        type: "Credt card",
        account: "032654 987465",
        existing: false,
        modified: "04/12/2018",
        limit: 10000
      
    ]
  ,
  
    name: "Mr John Doe -3409865, Mrs Jane Doe -34098365",
    id: 34098365,
    entityType: "business",
    facilities: [
      
        type: "Overdraft",
        account: "032654 987465",
        existing: false,
        modified: "04/12/2018",
        limit: 10000
      
    ]
  ,
  
    name: "Mr Jack",
    id: 34098365,
    entityType: "mixed",
    facilities: [
      
        type: "Overdraft",
        account: "032654 987465",
        existing: false,
        modified: "04/12/2018",
        limit: 10000
      
    ]
  
];


const entityIndex =  personal: 1, business: 2, mixed: 3 ;

let result = entities.sort((a, b) => 
  if (a.name > b.name) return -1;
  if (a.name < b.name) return 1;

  let et = entityIndex[a.entityType] - entityIndex[b.entityType];
  if (et != 0) return et;

  const aMinLimit = Math.min(...a.facilities.map(i => i.limit));
  const bMinLimit = Math.min(...b.facilities.map(i => i.limit));

  return bMinLimit - aMinLimit;

)

console.log(JSON.stringify(result));

【讨论】:

【参考方案3】:

试试

eType = personal:1, business:2, mixed:3;

entities.sort((a,b) => 
   if(a.name>b.name) return 1;
   if(a.name<b.name) return -1;

   let et=eType[a.entityType]-eType[b.entityType];
   return et;   
)

entities.forEach(e=> e.facilities.sort((a,b)=> b.limit - a.limit ))

let entities = [
        
          name: "zBroomsticks PTY",
          id: 34098365,
          entityType: "personal",
          facilities: [
            
              type: "Home loan",
              account: "032654 987465",
              existing: true,
              modified: "04/12/2018",
              limit: 100000
            ,
            
              type: "Credt card",
              account: "032654 987465",
              existing: false,
              modified: "04/12/2018",
              limit: 200000
            ,
            
              type: "Credt card",
              account: "032654 987465",
              existing: false,
              modified: "04/12/2018",
              limit: 10000
            ,
            
              type: "Credt card",
              account: "032654 987465",
              existing: false,
              modified: "04/12/2018",
              limit: 10000
            
          ]
        ,
        
          name: "Mr John Doe -3409865, Mrs Jane Doe -34098365",
          id: 34098365,
          entityType: "business",
          facilities: [
            
              type: "Overdraft",
              account: "032654 987465",
              existing: false,
              modified: "04/12/2018" ,
              limit: 10000
            
          ]
        ,

          name: "Mr Jack",
          id: 34098365,
          entityType: "mixed",
          facilities: [
            
              type: "Overdraft",
              account: "032654 987465",
              existing: false,
              modified: "04/12/2018",
              limit: 10000
            
          ]
        
      ];
      
      
eType = personal:1, business:2, mixed:3;

entities.sort((a,b) => 
   if(a.name>b.name) return 1;
   if(a.name<b.name) return -1;
   
   let et=eType[a.entityType]-eType[b.entityType];
   return et;   
)

entities.forEach(e=> e.facilities.sort((a,b)=> b.limit - a.limit ))

console.log(entities);

【讨论】:

以上是关于如何在javascript中对嵌套的对象数组进行排序?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Javascript 中对对象进行切片?

如何通过嵌套对象属性对 JavaScript 对象数组进行排序?

在javascript中对具有偏移量的对象数组进行排序

sort方法实际应用详解---javascript中对一个对象数组按照对象某个属性进行排序

如何在javascript中对多维数组进行排序

如何在javascript中对字母数字数组进行排序[重复]