简化的 javascript for 循环

我有几个级别深的 javscript 对象。所有级别都是对象,除了最终级别是我需要排序的数组。


到目前为止,我的代码如下所示:


for (let group in objRes) {

    if (objRes.hasOwnProperty(group)) {

        for (let type in objRes[group]) {

            if (objRes[group].hasOwnProperty(type)) {

                for (let name in objRes[group][type]) {

                    if (objRes[group][type].hasOwnProperty(name)) {

                        for (let tenor in objRes[group][type][name]) {

                            if (objRes[group][type][name].hasOwnProperty(tenor)) {

                                objRes[group][type][name][tenor] = objRes[group][type][name][tenor].sort((x,y)=>x.date>y.date);

                            }

                        }

                    }

                }

            }

        }

    }

}

级别 ( group, type, name, tenor) 都是字符串,最后一级数组成员如下所示:{date:'2019-12-25',value:35}


所以objRes看起来像


{

group1:

    {type1:

        {name1:

            {tenor1:[{date:'2019-12-25',value:35},...],

         name2 :{...}

         }

    },

    {type2 :{...}},

group2:{...}

}


有没有聪明的方法来简化这个?


您可以假设级别数已知或未知。


当年话下
浏览 164回答 2
2回答

潇湘沐

您可以为此使用递归函数。很难根据问题中的信息给出一个确切的例子,但例如:function process(obj) {&nbsp; &nbsp; // Loop through the values of the own properties of the object&nbsp; &nbsp; for (const value of Object.values(obj)) {&nbsp; &nbsp; &nbsp; &nbsp; // Is this the termination condition?&nbsp; &nbsp; &nbsp; &nbsp; if (Array.isArray(value)) { // <== A guess at the condition, adjust as needed&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // We've reached the bottom&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; value.sort((x, y) => x.date.localeCompare(y.date)); // <== Note correction, you can't just return the result of `>`&nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Not the termination, recurse&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; process(value);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}使用猜测数据的实时示例:function process(obj) {&nbsp; &nbsp; // Loop through the values of the own properties of the object&nbsp; &nbsp; for (const value of Object.values(obj)) {&nbsp; &nbsp; &nbsp; &nbsp; // Is this the termination condition?&nbsp; &nbsp; &nbsp; &nbsp; if (Array.isArray(value)) { // <== A guess at the condition, adjust as needed&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // We've reached the bottom&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; value.sort((x, y) => x.date.localeCompare(y.date)); // <== Note correction, you can't just return the result of `>`&nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Not the termination, recurse&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; process(value);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}const objRes = {&nbsp; &nbsp; group1: {&nbsp; &nbsp; &nbsp; &nbsp; type1: {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name1: {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tenor1: [&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {date: '2019-12-23', value: 35},&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {date: '2019-12-25', value: 32},&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {date: '2019-12-24', value: 30},&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; },&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name2 :[]&nbsp; &nbsp; &nbsp; &nbsp; },&nbsp; &nbsp; &nbsp; &nbsp; type2: {}&nbsp; &nbsp; },&nbsp; &nbsp; group2: {}};process(objRes);console.log(JSON.stringify(objRes, null, 4));.as-console-wrapper {&nbsp; &nbsp; max-height: 100% !important;}一些注意事项:您可以通过使用来避免for-in/hasOwnProperty组合Object.values。您可以使用 遍历这些值for-of。必须有一些终止条件告诉函数何时到达“底部”。在那个例子中,我使用了Array.isArray因为你在最后一级排序。Array.prototype.sort&nbsp;直接修改数组,不需要使用它的返回值。您传递给的函数sort必须返回负数、0 或正数,而不是布尔值(更多信息请点击此处)。由于您的date值在yyyy-MM-dd形式上似乎是字符串,因此您可以使用localeCompare它(因为在这种格式中,字典比较也是日期比较)。

叮当猫咪

这个替代 TJ Crowder 的答案采用了那里提到的几个决策点,并使它们显式函数调用。const process = (test, transform, data) =>&nbsp; typeof data == "object"&nbsp; &nbsp; ? ( Array .isArray (data)&nbsp; &nbsp; &nbsp; &nbsp;? (xs) => xs .map (([_, x]) => x)&nbsp; &nbsp; &nbsp; &nbsp;: Object .fromEntries&nbsp; &nbsp; &nbsp; ) ( Object .entries (data) .map (([k, v]) =>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; [k, test (k, v) ? transform (v) : process (test, transform, v)]&nbsp; &nbsp; &nbsp; ))&nbsp; &nbsp; : data&nbsp;&nbsp;它接受两个函数以及您的数据对象。第一个是测试您是否遇到了要按摩的嵌套值。所以我们可以想象像(k, v) => k .startsWith ('tenor')或 之类的东西(k, v) => Array .isArray (v)。第二个函数接受该条目处的值并返回一个更新的值,可能是(v) => v . sort((a, b) => a .date .localeCompare (b .date))。(注意:您的排序调用是有问题的。不要使用.sort ((a, b) => a < b),它返回一个布尔值,然后被强制转换为 a0或 a 1,而适当的比较器应该返回-1when a < b。如果您可以与 进行比较<,那么这应该始终有效(a, b) =>&nbsp; a < b ? -1 : a > b ? 1 : 0。我不”不知道是否有比使用 .sort((a,b) => a>b) 对数组进行排序更完整的问题。为什么?。)您可以在此代码段中看到它的运行情况:const process = (test, transform, data) =>&nbsp; typeof data == "object"&nbsp; &nbsp; ? ( Array .isArray (data)&nbsp; &nbsp; &nbsp; &nbsp; ? (xs) => xs .map (([_, x]) => x)&nbsp; &nbsp; &nbsp; &nbsp; : Object .fromEntries&nbsp; &nbsp; &nbsp; ) ( Object .entries (data) .map (([k, v]) =>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; [k, test (k, v) ? transform (v) : process (test, transform, v)]&nbsp; &nbsp; &nbsp; ))&nbsp; &nbsp; : data&nbsp; &nbsp;&nbsp;const dateSort = (xs) => xs .slice (0) .sort ((a, b) => a .date .localeCompare (b .date))const objRes = {&nbsp; &nbsp; group1: {&nbsp; &nbsp; &nbsp; &nbsp; type1: {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name1: {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tenor1: [&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {date: '2019-12-23', value: 35},&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {date: '2019-12-25', value: 32},&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {date: '2019-12-24', value: 30},&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; },&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name2: []&nbsp; &nbsp; &nbsp; &nbsp; },&nbsp; &nbsp; &nbsp; &nbsp; type2: {}&nbsp; &nbsp; },&nbsp; &nbsp; group2: {&nbsp; &nbsp; &nbsp; &nbsp; type3: [&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {date: '2020-01-03', value: 42},&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {date: '2019-01-01', value: 43},&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {date: '2019-01-02', value: 44},&nbsp; &nbsp; &nbsp; &nbsp; ]&nbsp; &nbsp; }};// This one only sorts the first group of datesconsole .log (&nbsp; process (&nbsp; &nbsp; (k, v) => k .startsWith ('tenor'),&nbsp; &nbsp; dateSort,&nbsp; &nbsp; objRes&nbsp; ))// This one sorts both groupsconsole .log (&nbsp; process (&nbsp; &nbsp; (k, v) => Array .isArray (v),&nbsp; &nbsp; dateSort,&nbsp; &nbsp; objRes&nbsp; ))代码有点密集。最外层条件仅在数据是对象时才应用我们的处理,如果不是则完整返回,如果是则执行以下处理:我们首先使用Object.entries将我们的对象转换为名称-值对,然后通过测试每一对来映射该对象,看看我们是否遇到了应该转换的东西,并返回转换后的值或对值进行递归的结果。也许最棘手的一点是:&nbsp; &nbsp; &nbsp; ( Array .isArray (data)&nbsp; &nbsp; &nbsp; &nbsp; ? (xs) => xs .map (([_, x]) => x)&nbsp; &nbsp; &nbsp; &nbsp; : Object .fromEntries&nbsp; &nbsp; &nbsp; )在这里,我们只选择一个函数应用到转换后的对上,将其重新变成一个整体。如果它是一个数组,我们跳过键并返回一个值数组。如果不是,我们就用它们Object.fromEntries来创建一个对象。如果Object.entries是不是在你的环境中使用,很容易垫片。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript