【问题标题】:Javascript - Sort Array of objects by 2 PropertiesJavascript - 按 2 个属性对对象数组进行排序
【发布时间】:2017-08-17 17:19:49
【问题描述】:

我想按 2 个不同的属性对对象数组进行排序。

这些是我的对象

array = [{ resVal: "25FA15", resFlow: 49, resName: "Rendimiento Tri-Seal Completo", resPhoto: "Tri-Sealseries.png", resHP: 1.5 },
 { resVal: "25FA2", resFlow: 52, resName: "Rendimiento Tri-Seal Completo", resPhoto: "Tri-Sealseries.png", resHP: 2 },
{ resVal: "45FA2", resFlow: 53, resName: "Rendimiento Hi-Cap Completo", resPhoto: "HighCapseries.png", resHP: 2 },
{ resVal: "35FA2", resFlow: 59, resName: "Rendimiento Hi-Cap Completo", resPhoto: "HighCapseries.png", resHP: 2 }]

我想按较高的“resFlow”值对数组进行排序,但使用最低的“resHP”值。

我想这样放置我的数组:

array = [{ resVal: "25FA15", resFlow: 49, resName: "Rendimiento Tri-Seal Completo", resPhoto: "Tri-Sealseries.png", resHP: 1.5 },
{ resVal: "35FA2", resFlow: 59, resName: "Rendimiento Hi-Cap Completo", resPhoto: "HighCapseries.png", resHP: 2 },
{ resVal: "45FA2", resFlow: 53, resName: "Rendimiento Hi-Cap Completo", resPhoto: "HighCapseries.png", resHP: 2 },
 { resVal: "25FA2", resFlow: 52, resName: "Rendimiento Tri-Seal Completo", resPhoto: "Tri-Sealseries.png", resHP: 2 }]

希望有人可以帮助我。

谢谢。

【问题讨论】:

  • 你的意思是要先按resHP从低到高排序,然后,对于具有相同值的那些,再按resFlow从高到低排序?
  • 发帖前请search。如果您滚动浏览链接问题的已接受答案,您会发现答案也向您展示了如何处理多个属性。
  • @T.J.Crowder,被骗的目标太可怕了。
  • @T.J.Crowder 我做到了,但我也没有找到答案。
  • @NinaScholz:那里的答案回答了这个问题,这是标准。我相信你可以找到另外四个。对于这个问题,我们不需要另一个答案。

标签: javascript arrays sorting


【解决方案1】:

您可以对指定的键顺序及其排序顺序使用链式方法。

数组按属性排序

  • resHP,升序和
  • resFlow,降序。

它适用于计算增量,这反映了两个对象的关系。如果值为零,则两个值相等,计算并返回下一个增量。

var array = [{ resVal: "25FA15", resFlow: 49, resName: "Rendimiento Tri-Seal Completo", resPhoto: "Tri-Sealseries.png", resHP: 1.5 }, { resVal: "25FA2", resFlow: 52, resName: "Rendimiento Tri-Seal Completo", resPhoto: "Tri-Sealseries.png", resHP: 2 }, { resVal: "45FA2", resFlow: 53, resName: "Rendimiento Hi-Cap Completo", resPhoto: "HighCapseries.png", resHP: 2 }, { resVal: "35FA2", resFlow: 59, resName: "Rendimiento Hi-Cap Completo", resPhoto: "HighCapseries.png", resHP: 2 }];

array.sort(function (a, b) {
    return a.resHP - b.resHP || b.resFlow - a.resFlow;
});

console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

    【解决方案2】:

    要求是按resHP 属性升序​​排序,然后对于任何平局,按resFlow 属性降序排序。

    现在,Javascript 的Array.prototype.sort 函数允许我们对数组进行排序。它接受一个参数,即 "compareFunction"。 compareFunction 接受两个参数,它们是要比较的数组的元素,它必须返回它们在预期结果数组中的相对位置。

    function compareFunction (itemA, itemB) {...}
    

    如果b 在结果中位于a 之前,

    compareFunction(a, b) 返回一个数值大于零

    如果b 在结果中位于a 之后,则

    compareFunction(a, b) 返回一个数值小于零

    如果ab 在对数组进行排序时在相对顺序方面被认为是等效的,则

    compareFunction(a, b) 返回。例如,在对[5, 3, 5] 进行排序时,两个 5 被认为是等效的,因此当调用 compareFunction(5,5) 时数组应该返回 0。

    对于字符串排序,不需要提供compareFunction。按照规范,当不提供 compareFunction 时,数组中的每个值都会转换为字符串,然后进行排序。这是一个例子:

    console.log('["z", "ct", "a", "aa", "ab", "bc"].sort(): ', ["z", "ct", "a", "aa", "ab", "bc"].sort());

    常见错误:

    不使用 compareFunction 比较数字

    虽然 compareFunction 按规范是可选的,但如果在对数字或其他对象进行排序时未提供,可能会导致结果不正确。考虑下面的例子:

    console.log("[1, 2, 5, 3, 0, 20].sort(): ", [1, 2, 5, 3, 0, 20].sort());

    这里 20 出现在 3 之前,因为每个数字在比较之前都被转换为字符串,并且由于在字典中(如果有这样的字典)中“20”在“3”之前,它在结果中出现在“3”之上。

    从 compareFunction 返回布尔值而不是数值

    这是我在原始答案中的错误。

    当您从 compareFunction 返回布尔值而不是数字时,布尔值将转换为数字。这意味着true 将变为 1,false 将变为 0,但您不会返回 -1。

    var array = [
      {
        compareThis: 1,
        originalIndex: 1
      },
      {
        compareThis: 2,
        originalIndex: 2
      },
      {
        compareThis: -1,
        originalIndex: 3
      },
      {
        compareThis: -2,
        originalIndex: 4
      }
    ];
    
    console.log(array.sort((a, b) => a.compareThis > b.compareThis));

    这里的结果是未排序的,相同的数组,因为2和-1比较时,比较2>-1返回false,转换为0。但是当compareFunction返回0时,表示两个元素的顺序应保持不变。因此数组没有得到排序。

    对这个数组进行排序的正确方法是:

    var array = [
      {
        compareThis: 1,
        originalIndex: 1
      },
      {
        compareThis: 2,
        originalIndex: 2
      },
      {
        compareThis: -1,
        originalIndex: 3
      },
      {
        compareThis: -2,
        originalIndex: 4
      }
    ];
    
    console.log(array.sort((a, b) => a.compareThis - b.compareThis));

    因此,解决问题中提出的问题的正确方法是:

    var array = [{ resVal: "25FA15", resFlow: 49, resName: "Rendimiento Tri-Seal Completo", resPhoto: "Tri-Sealseries.png", resHP: 1.5 },
     { resVal: "25FA2", resFlow: 52, resName: "Rendimiento Tri-Seal Completo", resPhoto: "Tri-Sealseries.png", resHP: 2 },
    { resVal: "45FA2", resFlow: 53, resName: "Rendimiento Hi-Cap Completo", resPhoto: "HighCapseries.png", resHP: 2 },
    { resVal: "35FA2", resFlow: 59, resName: "Rendimiento Hi-Cap Completo", resPhoto: "HighCapseries.png", resHP: 2 }];
    
    
    // The requirement is to sort ascending by resHP property and then for any ties, sort descending by resFlow property.
    /* array.sort(function(a, b) {
      if (a.resHP > b.resHP) {
        return 1;
      } else if (a.resHP === b.resHP) {
        if (a.resFlow > b.resFlow) {
          return -1;
        } else if (a.resFlow === b.resFlow) {
          return 0;
        } else {
          return 1;
        }
      } else {
        return -1;
      }
    }); */
    
    // Simplified to the following as we are working with numbers.
    array.sort(function sortByResHP(a, b) {
      return (a.resHP - b.resHP) !== 0 ? (a.resHP - b.resHP) : (b.resFlow - a.resFlow);
    });
    
    console.log("Result: ", array);

    当然,这可以进一步缩短,如另一个答案所示。我将保留较长版本的 compareFunction 以使其更易于阅读。


    原始(错误)答案

    您可以为此使用Array#sort

    array = [{ resVal: "25FA15", resFlow: 49, resName: "Rendimiento Tri-Seal Completo", resPhoto: "Tri-Sealseries.png", resHP: 1.5 },
     { resVal: "25FA2", resFlow: 52, resName: "Rendimiento Tri-Seal Completo", resPhoto: "Tri-Sealseries.png", resHP: 2 },
    { resVal: "45FA2", resFlow: 53, resName: "Rendimiento Hi-Cap Completo", resPhoto: "HighCapseries.png", resHP: 2 },
    { resVal: "35FA2", resFlow: 59, resName: "Rendimiento Hi-Cap Completo", resPhoto: "HighCapseries.png", resHP: 2 }]
    
    
    array.sort(function(d1,d2) {
      if(d1.resHP == d2.resHP) {
        return d1.resFlow < d2.resFlow;
      } else {
        return d1.resHP > d2.resHP;
      }
    });
    
    console.log(array);
    

    【讨论】:

    • 这是一个不好的例子,因为它不尊重排序回调的预期返回值。 sort 需要获得小于零、零或大于零的值。这个答案只返回零和一。例如,如果您反转 d1d2,这使得它不是对称的。
    • @NinaScholz 我从来没有注意到这一点。感谢您的解释! :)
    • 虽然我认为@NinaScholz 的答案更清晰,但我想赞扬 nisarg 完成并修复了他们的答案,并详细解释了正在发生的事情。干得好!
    【解决方案3】:

    这是一种按多个值对对象数组进行排序的简单方法

    arr.sort((a,b) => a.firstVal.localeCompare(b.firstVal) || a.secondVal.localeCompare(b.secondVal))
    

    所以在你的情况下它会是

    array.sort((a,b) => a.resHP.localeCompare(b.resHP) || b.resFlow.localeCompare(a.resFlow)
    

    【讨论】:

      【解决方案4】:

      将此视为更通用的解决方案:

      function sortArrayByTwoProperties(array, prop1, asc1 = true, prop2, asc2 = true) {
          return array.sort((a, b) => (
              (asc1 ? a[prop1] - b[prop1] : b[prop1] - a[prop1])
              || (asc2 ? a[prop2] - b[prop2] : b[prop2] - a[prop2])
          ));
      }
      
      array = [{ resVal: "25FA15", resFlow: 49, resName: "Rendimiento Tri-Seal Completo", resPhoto: "Tri-Sealseries.png", resHP: 1.5 },
       { resVal: "25FA2", resFlow: 52, resName: "Rendimiento Tri-Seal Completo", resPhoto: "Tri-Sealseries.png", resHP: 2 },
      { resVal: "45FA2", resFlow: 53, resName: "Rendimiento Hi-Cap Completo", resPhoto: "HighCapseries.png", resHP: 2 },
      { resVal: "35FA2", resFlow: 59, resName: "Rendimiento Hi-Cap Completo", resPhoto: "HighCapseries.png", resHP: 2 }]
      
      // I want to sort the array by the higher "resFlow" value, but with the lowest "resHP" value.
      
      // resHP ascending, resFlow descending
      result = sortArrayByTwoProperties(array, "resHP", true, "resFlow", false);
      
      console.log(result);
      
      array_expected = [{ resVal: "25FA15", resFlow: 49, resName: "Rendimiento Tri-Seal Completo", resPhoto: "Tri-Sealseries.png", resHP: 1.5 },
      { resVal: "35FA2", resFlow: 59, resName: "Rendimiento Hi-Cap Completo", resPhoto: "HighCapseries.png", resHP: 2 },
      { resVal: "45FA2", resFlow: 53, resName: "Rendimiento Hi-Cap Completo", resPhoto: "HighCapseries.png", resHP: 2 },
       { resVal: "25FA2", resFlow: 52, resName: "Rendimiento Tri-Seal Completo", resPhoto: "Tri-Sealseries.png", resHP: 2 }]
       

      【讨论】:

        猜你喜欢
        • 2011-09-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-13
        相关资源
        最近更新 更多