比较JavaScript对象数组以获取最小值/最大值

7 浏览
0 Comments

比较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")来实现这一点?

0
0 Comments

在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')`。

这篇文章对我来说非常有帮助!谢谢!

0
0 Comments

使用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(不是一个数字),因为函数期望接收多个数字参数。

希望这个回答不算晚。

0
0 Comments

比较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方法等多种方法来解决。每种方法都有其优缺点,可以根据具体需求选择合适的方法。

0