获取对象属性中最小/最大值的快速方法

129

我在JavaScript中有一个对象,它长得像这样:

{ "a":4, "b":0.5 , "c":0.35, "d":5 }

有没有一种快速的方法可以在不必遍历所有属性的情况下获取属性中的最小值和最大值?因为我拥有的对象非常大,并且我需要每两秒获取一次最小/最大值。(对象的值保持变化)。


3
@Oleg:鉴于目前只有这些信息,很可能是JSON格式。 Youssef:将JSON解析为对象,并迭代其属性。 - Felix Kling
2
JSON是对象的字符串表示。当您将JSON解析为一个对象时,它不再处于JSON格式中。 - altschuler
这是否意味着每两秒钟您都会获得新的JSON,其中包含所有数据? - Felix Kling
不需要。我有数据,每两秒钟对某些字段进行数学运算,然后需要获取新的最小/最大值。 - Y2theZ
1
我在您的问题中自作主张地修复了JSON->对象,因为评论证实这正是您的意思。 - Oleg V. Volkov
显示剩余6条评论
16个回答

198

更新:现代版本(ES6+)

let obj = { a: 4, b: 0.5 , c: 0.35, d: 5 };

let arr = Object.values(obj);
let min = Math.min(...arr);
let max = Math.max(...arr);

console.log( `Min value: ${min}, max value: ${max}` );

尝试使用这个:

let obj = { a: 4, b: 0.5 , c: 0.35, d: 5 };
var arr = Object.keys( obj ).map(function ( key ) { return obj[key]; });

然后:

var min = Math.min.apply( null, arr );
var max = Math.max.apply( null, arr );

实时演示: http://jsfiddle.net/7GCu7/1/


22
还可以使用max = Object.keys(obj).reduce(function(m, k){ return obj[k] > m ? obj[k] : m }, -Infinity);来实现。 - levi
4
现在也可以这样做:Math.max(...arr); - cmac
1
@cmac 我已经添加了一个ES6版本。 - Šime Vidas
@ŠimeVidas - Math.min和max函数中的三个点代表什么?谢谢。 - AME
2
@AME 在此阅读:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Spread_operator - Šime Vidas
显示剩余6条评论

23

在一般情况下,没有方法可以找到最大/最小值而不是通过循环遍历所有的n个元素(如果你从1到n-1,怎么知道元素n是否比当前的最大/最小值更大或更小?)。

您提到的值每隔几秒钟就会发生变化。如果您确切地知道哪些值发生了变化,您可以从您先前的最大/最小值开始,仅与新值进行比较,但即使在这种情况下,如果其中一个被修改的值是您的旧最大/最小值,则可能需要再次循环遍历它们。

另一个替代方案 - 再次强调,仅当更改的值的数量很小的情况下 - 将是将值存储在如树或堆之类的结构中,并且随着新值的到来适当地插入(或更新)它们。但是,基于您的问题,是否能够做到这一点并不清楚。

如果您想在遍历所有元素时获取给定列表的最大/最小元素,则可以使用以下代码片段之类的东西,但您将无法在不遍历它们的情况下实现此目标。

var list = { "a":4, "b":0.5 , "c":0.35, "d":5 };
var keys = Object.keys(list);
var min = list[keys[0]]; // ignoring case of empty list for conciseness
var max = list[keys[0]];
var i;

for (i = 1; i < keys.length; i++) {
    var value = list[keys[i]];
    if (value < min) min = value;
    if (value > max) max = value;
}

2
这并没有描述如何获取对象属性的最小/最大值。 - FistOfFury
你正在迭代一个对象,而不是一个列表。minmax未定义。你是否想使用for in循环? - tonix

14

你可以尝试:

const obj = { a: 4, b: 0.5 , c: 0.35, d: 5 };
const max = Math.max.apply(null, Object.values(obj));
console.log(max) // 5

12

minmax必须遍历输入数组——否则它们怎么能找到最大或最小的元素呢?

因此,只需要一个快速的for..in循环就可以正常工作。

var min = Infinity, max = -Infinity, x;
for( x in input) {
    if( input[x] < min) min = input[x];
    if( input[x] > max) max = input[x];
}

1
这对于IE7/8非常好。感谢@Niet the Dark Absol。 - ojhawkins
并不一定是通过循环数组来获取最小值和最大值。更可行的方法是对数组进行快速排序,并根据该结果选择最小值和最大值。 - goonerify
8
@goonerify 最快的排序算法是O(n log n),但它本质上比只需一次扫描的O(n)要慢... - Niet the Dark Absol

6
// 1. iterate through object values and get them
// 2. sort that array of values ascending or descending and take first, 
//    which is min or max accordingly
let obj = { 'a': 4, 'b': 0.5, 'c': 0.35, 'd': 5 }
let min = Object.values(obj).sort((prev, next) => prev - next)[0] // 0.35
let max = Object.values(obj).sort((prev, next) => next - prev)[0] // 5

4
获取最大值和最小值的键

var list = { "a":4, "b":0.5 , "c":0.35, "d":5 };
var keys = Object.keys(list);
var min = keys[0]; // ignoring case of empty list for conciseness
var max = keys[0];
var i;

for (i = 1; i < keys.length; i++) {
    var value = keys[i];
    if (list[value] < list[min]) min = value;
    if (list[value] > list[max]) max = value;
}

console.log(min, '-----', max)


4
你可以使用reduce()函数。
例如:
let obj = { "a": 4, "b": 0.5, "c": 0.35, "d": 5 }

let max = Object.entries(obj).reduce((max, entry) => entry[1] >= max[1] ? entry : max, [0, -Infinity])
let min = Object.entries(obj).reduce((min, entry) => entry[1] <= min[1] ? entry : min, [0, +Infinity])

console.log(max) // ["d", 5]
console.log(min) // ["c", 0.35]

4

您还可以尝试使用 Object.values

const points = { Neel: 100, Veer: 89, Shubham: 78, Vikash: 67 };

const vals = Object.values(points);
const max = Math.max(...vals);
const min = Math.min(...vals);
console.log(max);
console.log(min);


4
// Sorted
let Sorted = Object.entries({ "a":4, "b":0.5 , "c":0.35, "d":5 }).sort((prev, next) => prev[1] - next[1])
>> [ [ 'c', 0.35 ], [ 'b', 0.5 ], [ 'a', 4 ], [ 'd', 5 ] ]


//Min:
Sorted.shift()
>> [ 'c', 0.35 ]

// Max:
Sorted.pop()
>> [ 'd', 5 ]

3
这里有一个解决方案,可以让你返回键并且只做一次循环。它按值对对象的条目进行排序,然后返回第一个和最后一个。
此外,它返回已排序的对象,可以替换现有的对象,这样将来的排序会更快,因为它已经被半排序了 = 比O(n)好。重要的是要注意,在ES6中对象保留其顺序。

const maxMinVal = (obj) => {
  const sortedEntriesByVal = Object.entries(obj).sort(([, v1], [, v2]) => v1 - v2);

  return {
    min: sortedEntriesByVal[0],
    max: sortedEntriesByVal[sortedEntriesByVal.length - 1],
    sortedObjByVal: sortedEntriesByVal.reduce((r, [k, v]) => ({ ...r, [k]: v }), {}),
  };
};

const obj = {
  a: 4, b: 0.5, c: 0.35, d: 5
};

console.log(maxMinVal(obj));


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接