繁体   English   中英

为所有孩子递归排序对象数组

[英]sort array of objects recursively for all children

我有一个对象数组,其中包含许多级别的嵌套子项,我需要通过比较同一级别项的两个属性来对其进行排序。 数组有多个嵌套项,所以我提供了这个需要排序的最小数组。

每个项目至少有 3 个属性(路径、标题和上一个),并且一些项目可能具有与子项目相似的项目。

// unsorted array
const original = [
  {
    "path": "path3",
    "title": "title3",
    "previous": "title2",
    "children": [
      { "path": "child31", "title": "child31", "previous": null },
      { "path": "child32", "title": "child32", "previous": "child31" },
      { "path": "child33", "title": "child33", "previous": "child32" }
    ]
  },
  {
    "path": "path1",
    "title": "title1",
    "previous": null,
    "children": [
      { "path": "child11", "title": "child11", "previous": null },
      { "path": "child13", "title": "child13", "previous": "child12" },
      { "path": "child14", "title": "child14", "previous": "child13" },
      { "path": "child12", "title": "child12", "previous": "child11",
        "children": [
          { "path": "child123", "title": "child123", "previous": "child122" },
          { "path": "child121", "title": "child121", "previous": null },
          { "path": "child122", "title": "child122", "previous": "child121",
            "children": [
              { "path": "child1221", "title": "child1221", "previous": null, 
                "children": [
                  {
                    "path": "child12211",
                    "title": "child12211",
                    "previous": null
                  },
                  {
                    "path": "child1222",
                    "title": "child1222",
                    "previous": "child1221"
                  }
                ]
              },
              {
                "path": "child1224",
                "title": "child1224",
                "previous": "child1223"
              },
              {
                "path": "child1222",
                "title": "child1222",
                "previous": "child1221"
              },
              {
                "path": "child1223",
                "title": "child1223",
                "previous": "child1222",
                "children": [
                  {
                    "path": "child12231",
                    "title": "child12231",
                    "previous": null
                  }
                ]
              }
            ]
          }
      ]}
    ]
  },
  { "path": "path2", "title": "title2", "previous": "title1" }
];

我需要通过比较同一父项中项目的先前值和标题值来对该数组进行排序。 如果 previous 是任何项目的 null,那将是该父项中的第一项,对于下一项,previous 将是其上一个兄弟的标题,依此类推。

这是我的排序 function:

const sortNav = items => {
  let result = [...items].sort(function (a, b) {
    if(a.title === b.previous || a.previous === null) {
      return -1;
    } 
    if (a.previous === b.title || b.previous === null) {
      return 1;
    }
    return 0;
  })

  for(let i = 0; i < items.length; i++) {
    if (items[i].children && items[i].children.length) {
      items[i].children = sortNav(items[i].children);
    }
  }
  return result;
};

我正在像这样消费 function

const sorted = sortNav(original);

原始数组

原始排序数组

我会说你需要定义一个排序 function 并像这样递归地传递它

var origArray = ['a','b','c',['a','b','c']];

function SortRecursive(a, b){
 let aArray = Array.isArray(a);
 let bArray = Array.isArray(b);

 if(aArray == bArray){
  if(aArray){
   a.sort(SortRecursive);
   b.sort(SortRecursive);
   return a[0] > b[0] ? -1 : a[0] < b[0] ? 1 : 0;
  } else {
   return a > b ? -1 : a < b ? 1 : 0;
  }
 } else {
  return aArray && !bArray ? -1 : !aArray && bArray ? 1 : 0;
 }
}

origArray.sort(SortRecursive);

这可能与您想要对数据进行排序的方式不完全一样,因为我们没有得到您的数据的示例,但您应该能够看到我对子 arrays 做了什么。

另一方面,这也会对同一个数组进行多次排序,因此可能应该想出一种方法来识别已经排序的子 arrays。

问题是您正在对项目 object 的子items进行排序,但从 function 返回result object。 因此,在对列表进行排序之前对子项进行排序。

 const sortNav = items => { for(let i = 0; i < items.length; i++) { if (items[i].children && items[i].children.length) { console.log("calling sort for children of ", items[i].title, items[i].children) items[i].children = sortNav(items[i].children); } } let result = [...items].sort(function (a, b) { if(a.title === b.previous || a.previous === null) { console.log("comparing...", a.pathTitle, " > ", b.pathTitle) return -1; } if (a.previous === b.title || b.previous === null) { console.log("compare...", a.pathTitle, " < ", b.pathTitle) return 1; } return 0; }) console.log("sorted =>", result); return result; };

这应该照顾没有被分类的孩子。 但是根据您的示例数据,我还注意到对于以下两个元素的情况,排序 function 返回 0,这意味着它周围的元素永远不会正确排序。

 [{ "pathTitle": "set-up-standard-payments.md", "title": "Set up standard payments", "previous": "credit and debit card payments" }, { "pathTitle": "configure-payments", "title": "Configure Payments", "previous": "Add capabilities", "children": [ { "pathTitle": "alternative-payment-methods.md", "title": "Payment Methods", "previous": null } ] }]

鉴于您有点/有点尝试像链接列表一样重新排序列表,我建议使用以下 function 代替:-

 const reoderList = (items) => { var result = []; for(let i = 0; i < items.length; i++) { if (items[i].children && items[i].children.length) { items[i].children = reorderList(items[i].children); } } items.forEach(item => { if(item.previous === null) { result = [item, ...result]; } else { var index = result.findIndex(r => r.title === item.previous); if(index > -1) { result.splice(index+1,0,item); } else { result = [...result,item]; } } }); return result; };

编辑:从预期的 output 开始,您还需要之前的 === null 对象始终显示在顶部。 这可能需要对结果列表进行第二次传递以确保这一点。

暂无
暂无

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

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