比较JavaScript对象数组以获取最小值/最大值
比较JavaScript对象数组以获取最小值/最大值
我有一个对象数组,我想根据其中一个特定的对象属性来比较这些对象。这是我的数组:
var myArray = [ {"ID": 1, "Cost": 200}, {"ID": 2, "Cost": 1000}, {"ID": 3, "Cost": 50}, {"ID": 4, "Cost": 500} ]
我想专注于"cost"属性,并获得最小和最大值。我意识到我可以只获取成本值并将它们推入一个JavaScript数组中,然后运行Fast JavaScript Max/Min。
但是,是否有一种更简单的方法,通过绕过中间的数组步骤直接使用对象属性(在这种情况下是"Cost")来实现这一点?
在JavaScript中,比较对象数组以获取最小值/最大值是一个常见的需求。为了解决这个问题,可以使用`Array.prototype.reduce()`方法来执行聚合操作(如最小值、最大值、平均值等)并返回一个结果。
下面是一个使用`reduce()`方法来获取最小值的示例:
myArray.reduce(function(prev, curr) { return prev.Cost < curr.Cost ? prev : curr; });
在ES6中,可以使用箭头函数语法来定义内部函数,进一步简化代码:
myArray.reduce((prev, curr) => prev.Cost < curr.Cost ? prev : curr);
为了更方便使用,可以将这个函数附加到Array原型上:
Array.prototype.hasMin = function(attrib) { return (this.length && this.reduce(function(prev, curr){ return prev[attrib] < curr[attrib] ? prev : curr; })) || null; }
现在可以直接调用`hasMin()`方法来获取最小值:
myArray.hasMin('ID') // 结果: {"ID": 1, "Cost": 200} myArray.hasMin('Cost') // 结果: {"ID": 3, "Cost": 50} myEmptyArray.hasMin('ID') // 结果: null
需要注意的是,如果要使用这个方法,它并没有对每种情况进行完整的检查。如果传入的是一个原始类型的数组,它将会失败。如果检查的属性不存在,或者不是所有的对象都包含该属性,将会返回最后一个元素。下面这个版本增加了一些检查,但代码会变得更冗长:
Array.prototype.hasMin = function(attrib) { const checker = (o, i) => typeof(o) === 'object' && o[i] return (this.length && this.reduce(function(prev, curr){ const prevOk = checker(prev, attrib); const currOk = checker(curr, attrib); if (!prevOk && !currOk) return {}; if (!prevOk) return curr; if (!currOk) return prev; return prev[attrib] < curr[attrib] ? prev : curr; })) || null; }
这是一个性能最佳的答案,它不会修改数组,并且比其他方法更简洁。对于大型数据集(30列/10万行以上),这是最好的解决方案。
需要注意的是,第一个部分中有一个括号缺失的错误。
另外,如果在reduce函数检查数组的第一个元素时,`prev.Cost`会是undefined吗?还是会初始化为0?
补充:抱歉,刚刚看到了这个问题的解答[链接](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce)。简单回答:如果使用reduce时没有提供初始值,索引将从1开始。
是的,这一点很重要:如果reduce使用的累加器的类型与原始数组的元素类型不同,一定要提供一个初始值,否则累加器会以错误的类型开始。
如果数组为空,这个解决方案会抛出异常。
很好的观点。我刚刚进行了编辑,使其在这种情况下返回null。
我还添加了一些对其他可能引起问题的输入进行检查的代码,比如非对象或者某些对象缺少该属性。尽管对于大多数情况来说,这有点过于复杂。
如果不想修改原型,可以使用`call`或`apply`方法,例如`hasMin.call(myArray, 'Cost')`。
这篇文章对我来说非常有帮助!谢谢!
使用Math.min和Math.max函数可以实现对JavaScript对象数组进行比较并得到最小值和最大值的功能。在上述代码中,通过使用map函数将myArray数组中的cost属性映射为一个新数组,然后使用spread operator(扩展运算符)将新数组中的元素作为参数传递给Math.min和Math.max函数。
对于为什么需要使用spread operator的问题,是因为Math.max函数接受多个参数而不是一个数组。spread operator将数组转换为参数列表。例如,Math.max(...[1, 5, 9])等价于Math.max(1, 5, 9)。如果没有使用spread operator,Math.max(myArray)将返回NaN(不是一个数字),因为函数期望接收多个数字参数。
希望这个回答不算晚。
比较JavaScript对象数组以获得最小/最大值是一个常见的问题。有几种方法可以解决这个问题。
一种方法是循环遍历所有元素,并将其与最高/最低值进行比较。这种方法的缺点是创建一个数组并调用数组方法可能有些繁琐,因为这个操作实际上很简单。
另一种方法是使用reduce函数。这个函数可以将数组中的每个元素应用到一个函数,并将结果累加到一个最终值中。对于这个问题,可以使用reduce函数来找到最小或最大的值。
下面是使用循环和比较的方法来找到最小和最大值的示例代码:
var lowest = Number.POSITIVE_INFINITY; var highest = Number.NEGATIVE_INFINITY; var tmp; for (var i = myArray.length - 1; i >= 0; i--) { tmp = myArray[i].Cost; if (tmp < lowest) lowest = tmp; if (tmp > highest) highest = tmp; } console.log(highest, lowest);
这种方法在逻辑上是正确的,但有些冗余。我们可以通过将`lowest=highest=myArray[0]`来减少一次循环,并从索引1开始循环来优化代码。
另外,如果数组没有第一个元素,将会抛出错误。因此,我们需要进行额外的检查以避免这种情况,并可能降低性能。
如果你只是想返回对象本身而不是最小值,可以维护另一个变量来保存找到的最小值的对象。例如:
var lowestObject; for (var i = myArray.length - 1; i >= 0; i--) { tmp = myArray[i].Cost; if (tmp < lowest) { lowestObject = myArray[i]; lowest = tmp; } }
如果你使用ES6,你可以使用一行代码来解决这个问题:
Math.min(...myArray.map(o => o.Cost))
这个方法使用了ES6的扩展运算符和数组的map方法,它将每个对象的Cost属性映射到一个新的数组中,然后使用Math.min函数找到最小值。
另一个方法是使用数组的sort方法来排序数组,然后取第一个和最后一个元素作为最小和最大值:
myArray.sort((a, b) => a.Cost - b.Cost);
这个方法在较旧的JavaScript版本中是有效的,但在ES6中有更好的解决方案。
总之,比较JavaScript对象数组以获得最小/最大值是一个常见的问题,可以使用循环和比较、reduce函数、ES6的扩展运算符和map方法、sort方法等多种方法来解决。每种方法都有其优缺点,可以根据具体需求选择合适的方法。