Javascript - 按 2 个属性对对象数组进行排序

IT技术 javascript arrays sorting
2021-02-25 12:06:13

我想按 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 }]

希望可以有人帮帮我。

谢谢你。

4个回答

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

数组按属性排序

  • 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; }

要求是按resHP属性升序排序,然后对于任何关系,按resFlow属性降序排序

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

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

compareFunction(a, b)如果出现在结果之前,则返回一个大于零的数值ba

compareFunction(a, b)如果出现在结果之后,则返回一个小于零的数值ba

compareFunction(a, b)如果在对数组进行排序时的相对顺序方面被认为是等效的,返回例如,虽然排序两个 5 被认为是等效的,因此数组在调用时应该返回 0 ab[5, 3, 5]compareFunction(5,5)

对于字符串排序,compareFunction不需要提供 a 根据规范,当未提供 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将变为 1false并将变为 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);
@NinaScholz 我从来没有注意到这一点。感谢您的解释!:)
2021-04-27 12:06:13
虽然我认为@NinaScholz 的答案更清晰,但我想赞扬 nisarg 仔细检查并修复了他们的答案,并提供了对正在发生的事情的详细解释。干得好!
2021-04-29 12:06:13
这是一个不好的例子,因为它不尊重排序回调的预期返回值。sort需要得到小于零、零或大于零的值。这个答案只返回零和一。这使得它不是对称的,例如,如果你反转d1d2
2021-05-10 12:06:13

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

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)

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

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 }]