【问题标题】:TypeScript / JS -- sort an array of nested objects based on a property common to all objectsTypeScript / JS——基于所有对象共有的属性对嵌套对象数组进行排序
【发布时间】:2019-10-27 13:57:32
【问题描述】:

我正在学习 TypeScript 和 JS,并努力解决多个问题。其中之一就是这个,我手头有。说,我有一个 Application 对象数组。每个 Application 对象都有这种嵌套结构:

应用
|
----[文档类型]
---------|
--------------[文档]
------------------|
------------------------元数据

(每个Application 都有一个Document Type 数组。 每个Document Type 都有一个Document 数组。 每个Document 里面都有一个Metadata

所有三种对象类型——ApplicationDocument TypeDocument...在它们内部都有一个名为 name 的属性。 我想根据每个对象的name 属性的升序对整个Application 对象数组(以及递归嵌套对象)进行排序。我一直在尝试多个示例,但这些示例都只对根级对象 (Application) 进行排序,而不是嵌套对象。

这是我试过的一个这样的例子:

var simplePropertyRetriever = function(obj:any) {
      return obj.name;
     };

function sortArrayByName(propertyRetriever, arr:Application[]) {
   arr.sort(function (a, b) {
        var valueA = propertyRetriever(a);
        var valueB = propertyRetriever(b);

        if (valueA < valueB) {
            return -1;
        } else if (valueA > valueB) {
            return 1;
        } else {
            return 0;
        }
    });

  };

谁能告诉我怎么做?
我的示例 JSON 是这样的(我在这里按降序排列了对象,以更好地解释我的用例):

[
 {
  "name": "Application 2",
  "children": [
   {
    "name": "Operations Manual",
    "children": [
     {
      "name": "2nd-opsManual-app1",
      "metadata": {
       "size": 56,
       "fileExtension": "docx"
      }
     },
     {
      "name": "1st-opsManual-app1",
      "metadata": {
       "size": 56,
       "fileExtension": "pdf"
      }
     }
    ]
   },
   {
    "name": "Interface Contracts",
    "children": [
     {
      "name": "2nd-IntContracts-app1",
      "metadata": {
       "size": 56,
       "fileExtension": "docx"
      }
     },
     {
      "name": "1st-IntContracts-app1",
      "metadata": {
       "size": 56,
       "fileExtension": "pdf"
      }
     }
    ]
   }
  ]
 },
 {
  "name": "Application 2",
  "children": [
   {
    "name": "User Manual",
    "children": [
     {
      "name": "2nd-userManual-app2",
      "metadata": {
       "size": 56,
       "fileExtension": "docx"
      }
     },
     {
      "name": "1st-userManual-app2",
      "metadata": {
       "size": 56,
       "fileExtension": "pdf"
      }
     }
    ]
   },
   {
    "name": "System Design",
    "children": [
     {
      "name": "2nd-SystemDesign-app2",
      "metadata": {
       "size": 56,
       "fileExtension": "docx"
      }
     },
     {
      "name": "1st-SystemDesign-app2",
      "metadata": {
       "size": 56,
       "fileExtension": "pdf"
      }
     }
    ]
   }
  ]
 }
]

【问题讨论】:

    标签: javascript typescript


    【解决方案1】:

    您可以迭代数组并将子元素进行新的排序。

    function sort(array) {
        array.forEach(({ children = [] }) => sort(children));
        array.sort((a, b) => a.name.localeCompare(b.name));
    }
    
    var data = [{ name: "Application 2", children: [{ name: "Operations Manual", children: [{ name: "2nd-opsManual-app1", metadata: { size: 56, fileExtension: "docx" } }, { name: "1st-opsManual-app1", metadata: { size: 56, fileExtension: "pdf" } }] }, { name: "Interface Contracts", children: [{ name: "2nd-IntContracts-app1", metadata: { size: 56, fileExtension: "docx" } }, { name: "1st-IntContracts-app1", metadata: { size: 56, fileExtension: "pdf" } }] }] }, { name: "Application 2", children: [{ name: "User Manual", children: [{ name: "2nd-userManual-app2", metadata: { size: 56, fileExtension: "docx" } }, { name: "1st-userManual-app2", metadata: { size: 56, fileExtension: "pdf" } }] }, { name: "System Design", children: [{ name: "2nd-SystemDesign-app2", metadata: { size: 56, fileExtension: "docx" } }, { name: "1st-SystemDesign-app2", metadata: { size: 56, fileExtension: "pdf" } }] }] }];
    
    sort(data);
    
    console.log(data);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

    • 非常感谢...我将使用这个 sn-p。它更具可读性和简洁性。有没有办法可以扩展此解决方案以将参数名称作为参数? (这样它就可以用于所有对象中存在的任何其他参数,就像name
    【解决方案2】:

    您的代码正在运行,但您只是进行了浅层排序。如果您还需要对每个应用程序对象的子项进行排序,您可以递归地对每个应用程序对象的子项(如果存在)调用sortArrayByName

    var simplePropertyRetriever = function(obj) {
      return obj.name;
     };
    
    function sortArrayByName(propertyRetriever, arr) {
     arr.forEach(function(obj) {
          if (Array.isArray(obj.children)) {
            sortArrayByName(propertyRetriever, obj.children);
          }
     });
     arr.sort(function (a, b) {
          var valueA = propertyRetriever(a);
          var valueB = propertyRetriever(b);
    
          if (valueA < valueB) {
              return -1;
          } else if (valueA > valueB) {
              return 1;
          } else {
              return 0;
          }
      });
    };
    
    const data = [
     {
      "name": "Application 2",
      "children": [
       {
        "name": "Operations Manual",
        "children": [
         {
          "name": "2nd-opsManual-app1",
          "metadata": {
           "size": 56,
           "fileExtension": "docx"
          }
         },
         {
          "name": "1st-opsManual-app1",
          "metadata": {
           "size": 56,
           "fileExtension": "pdf"
          }
         }
        ]
       },
       {
        "name": "Interface Contracts",
        "children": [
         {
          "name": "2nd-IntContracts-app1",
          "metadata": {
           "size": 56,
           "fileExtension": "docx"
          }
         },
         {
          "name": "1st-IntContracts-app1",
          "metadata": {
           "size": 56,
           "fileExtension": "pdf"
          }
         }
        ]
       }
      ]
     },
     {
      "name": "Application 2",
      "children": [
       {
        "name": "User Manual",
        "children": [
         {
          "name": "2nd-userManual-app2",
          "metadata": {
           "size": 56,
           "fileExtension": "docx"
          }
         },
         {
          "name": "1st-userManual-app2",
          "metadata": {
           "size": 56,
           "fileExtension": "pdf"
          }
         }
        ]
       },
       {
        "name": "System Design",
        "children": [
         {
          "name": "2nd-SystemDesign-app2",
          "metadata": {
           "size": 56,
           "fileExtension": "docx"
          }
         },
         {
          "name": "1st-SystemDesign-app2",
          "metadata": {
           "size": 56,
           "fileExtension": "pdf"
          }
         }
        ]
       }
      ]
     }
    ];
    
    sortArrayByName(simplePropertyRetriever, data);
    
    console.log(data);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

    • 非常感谢。我真的很愚蠢,没有为递归做任何事情......并期望它递归地工作。
    猜你喜欢
    • 2018-07-02
    • 2023-01-06
    • 2021-02-23
    • 2019-07-11
    • 2011-07-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多