【问题标题】:Most performant way to sort a deeply nested array of objects by another deeply nested array of objects通过另一个深度嵌套的对象数组对深度嵌套的对象数组进行排序的最高效方法
【发布时间】:2019-01-10 19:29:09
【问题描述】:

作为一个例子 - 我已经包含一个元素 array 包含一个 object 有一个 Children 键,这是一个 对象数组,每个对象也有自己的Children键,其中包含另一个数组。

[
  {
    "Id": "1",
    "Children": [
      {
        "Id": "2",
        "Children": [
          {
            "Id": "10",
            "DisplayName": "3-4",
          },
          {
            "Id": "1000",
            "DisplayName": "5-6",
          },
          {
            "Id": "100",
            "DisplayName": "1-2",
          },
        ]
      }
    ]
  }
]

有一个第二个对象数组,我想比较第一个对象数组,目的是确保第一个数组与 第二个数组 对象的顺序相同,如果不是 - 然后 sort 直到它是。

这是第二个数组:

[
  {
    "Id": "1",
    "Children": [
      {
        "Id": "2",
        "Children": [
           {
            "Id": "100",
            "DisplayName": "1-2",
          },
          {
            "Id": "10",
            "DisplayName": "3-4",
          },
          {
            "Id": "1000",
            "DisplayName": "5-6",
          },
        ]
      }
    ]
  }
]

这将运行的数据可能高达数万 - 因此性能至关重要。

我目前正在尝试使用一种实用方法将第二个数组的每个元素转换为对象的键控对象,例如

{
   1:  {
        "Id": "1",
        "Children": [
          {
            "Id": "2",
            "Children": [
              {
                "Id": "4",
                "DisplayName": "3-4",
              },
              {
                "Id": "3",
                "DisplayName": "1-2",
              },
            ]
          }
        ]
      }
}

这允许从顶层快速查找。我想知道我是否应该一直这样做下去,或者是否有一种惯用的方式来实现这一点。我也考虑了递归。 已排序数组的顺序不基于 Id - 它是任意的。因此,无论如何都需要保留订单。

【问题讨论】:

  • 对象是否保证具有相同的深度,每个级别是否包含相同数量的子对象?
  • 只要一个键存在-另一个中的对应键将具有相同的深度是的。但是,参考中存在的键在被比较的数组中不存在。我将尝试使用您提供的示例,我可能需要使用 pluck / filter 来使两者相同,而不是运行递归函数。

标签: javascript arrays sorting object multidimensional-array


【解决方案1】:

假设每个对象的每个级别都存在相同的深度和所有 Id,使用一个递归函数,该函数在排序回调中使用 Array#findIndex() 匹配

function sortChildren(main, other) {
  other.forEach((o, i) => {
    if (o.children) {
      const mChilds = main[i].children, oChilds = o.children;
      
      oChilds.sort((a, b) => {
        return mChilds.findIndex(main => main.Id === a.Id) - mChilds.findIndex(main => main.Id === b.Id)
      });
      // call function again on this level passing appropriate children arrays in
      sortChildren(mChilds, oChilds)
    }
  })
}

sortChildren(data, newData);
console.log(JSON.stringify(newData, null, ' '))
<script>
  var data = [{
    "Id": "1",
    "Children": [{
      "Id": "2",
      "Children": [{
          "Id": "3",
          "DisplayName": "1-2",
        },
        {
          "Id": "4",
          "DisplayName": "3-4",
        },
      ]
    }]
  }]

  var newData = [{
    "Id": "1",
    "Children": [{
      "Id": "2",
      "Children": [{
          "Id": "4",
          "DisplayName": "3-4",
        },
        {
          "Id": "3",
          "DisplayName": "1-2",
        },
      ]
    }]
  }]

</script>

【讨论】:

  • 我必须排序的数据的问题是 id 参数不是升序/降序。无论如何,您将如何保留订单?
  • 我正在使用相关ID的索引
  • @zero_cool Id 的顺序?考虑具有可预测顺序的对象键是有风险的:stackoverflow.com/q/30076219/3294944(如果您的意思是数组索引位置,请忽略我的评论。:))
  • 没有。每个对象都是子数组的元素。该对象在其子数组中的索引。它是数组索引...与对象属性顺序无关
猜你喜欢
  • 2019-01-29
  • 1970-01-01
  • 2013-12-03
  • 2016-05-18
  • 1970-01-01
  • 2023-01-13
  • 2016-06-02
  • 2017-12-15
  • 1970-01-01
相关资源
最近更新 更多