Manera rápida de obtener los valores mínimo / máximo entre las propiedades del objeto

94

Tengo un objeto en javascript como este:

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

¿Existe una manera rápida de obtener el valor mínimo y máximo entre las propiedades sin tener que recorrerlas todas? porque el objeto que tengo es enorme y necesito obtener el valor mínimo / máximo cada dos segundos. (Los valores del objeto siguen cambiando).

Youssef
fuente
3
@Oleg: Bueno, dado solo esto, podría ser JSON. Youssef: analiza el JSON en un objeto e itera sobre sus propiedades.
Felix Kling
@ OlegV.Volkov Estoy usando JSON.parse () ¿no debería convertirlo en Json?
Youssef
@Youssef Era JSON (que es un valor de cadena) antes de analizar. Es un valor de objeto después del análisis.
Šime Vidas
2
JSON es la notación de cadena de objetos. Al analizar JSON a un objeto, que ya no está en el formato JSON es
Altschuler
1
Me tomé la libertad de arreglar JSON -> objeto en su pregunta, ya que los comentarios confirman que es lo que quiso decir.
Oleg V. Volkov

Respuestas:

19

No hay forma de encontrar el máximo / mínimo en el caso general sin recorrer todos los n elementos (si pasa de 1 a n-1, ¿cómo sabe si el elemento n no es más grande (o más pequeño) que el corriente max / min)?

Mencionaste que los valores cambian cada dos segundos. Si sabe exactamente qué valores cambian, puede comenzar con sus valores máximos / mínimos anteriores y comparar solo con los nuevos, pero incluso en este caso, si uno de los valores que se modificaron era su antiguo máximo / mínimo, puede Necesito recorrerlos nuevamente.

Otra alternativa, nuevamente, solo si la cantidad de valores que cambian es pequeña, sería almacenar los valores en una estructura como un árbol o un montón, y cuando lleguen los nuevos valores, los insertaría (o actualizaría) de manera apropiada. Pero si puede hacerlo, no está claro según su pregunta.

Si desea obtener el elemento máximo / mínimo de una lista determinada mientras recorre todos los elementos, puede usar algo como el fragmento a continuación, pero no podrá hacerlo sin pasar por todos ellos.

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;
}
carlosfigueira
fuente
2
Esto no describe cómo obtener los valores mínimo / máximo de las propiedades de un objeto.
FistOfFury
Está iterando sobre un objeto, no una lista. miny maxno están definidos. ¿Querías usar un for inbucle en su lugar?
tonix
1
Gracias @tonix, lo arreglé.
carlosfigueira
139

Actualización: versión moderna (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}` );


Respuesta original:

Prueba esto:

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

y entonces:

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

Demostración en vivo: http://jsfiddle.net/7GCu7/1/

Šime Vidas
fuente
21
También puedo hacerlomax = Object.keys(obj).reduce(function(m, k){ return obj[k] > m ? obj[k] : m }, -Infinity);
levi
4
También puede hacer esto ahora: Math.max(...arr);
cmac
1
@cmac He agregado una versión ES6.
Šime Vidas
@ ŠimeVidas - ¿Qué representan los 3 puntos en la función Math.min & max? Gracias
AME
12

miny maxtienen que recorrer la matriz de entrada de todos modos, ¿de qué otra manera encontrarían el elemento más grande o más pequeño?

Así que solo un for..inbucle rápido funcionará bien.

var min = Infinity, max = -Infinity, x;
for( x in input) {
    if( input[x] < min) min = input[x];
    if( input[x] > max) max = input[x];
}
Niet the Dark Absol
fuente
1
Esto es genial para IE7 / 8. Saludos @Niet the Dark Absol
ojhawkins
No es necesariamente cierto que min y max recorren la matriz para obtener sus valores. Es más factible que
clasifiquen rápidamente
7
@goonerify El tipo más rápido es O(n log n), que es inherentemente más lento que el O(n)que solo escanear una vez sería ...
Niet the Dark Absol
11

Tu podrías intentar:

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
Dave Kalu
fuente
5
// 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
Andrey Kudriavtsev
fuente
1
Se agregó una explicación.
Andrey Kudriavtsev
4

También puedes probar con 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);

Neel Rathod
fuente
3

Usando la biblioteca lodash puede escribir más corto

_({ "a":4, "b":0.5 , "c":0.35, "d":5 }).values().max();
Sergey Zhigalov
fuente
3

Aquí hay una solución que le permite devolver la clave también y solo hace un bucle. Ordena las entradas del Objeto (por val) y luego devuelve la primera y la última.

Además, devuelve el Objeto ordenado que puede reemplazar el Objeto existente para que las clasificaciones futuras sean más rápidas porque ya estará semi ordenado = mejor que O (n). Es importante tener en cuenta que los objetos conservan su orden en 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));

JBallin
fuente
¡Gracias! Estaba tratando de averiguar cómo obtener el máximo mientras aún conservaba la clave para ir con el valor. ¡Esto ayudó! :)
010011100101
2

Para estructuras anidadas de diferente profundidad, es decir {node: {leaf: 4}, leaf: 1}, esto funcionará (usando lodash o subrayado):

function getMaxValue(d){
    if(typeof d === "number") {
        return d;
    } else if(typeof d === "object") {
        return _.max(_.map(_.keys(d), function(key) {
            return getMaxValue(d[key]);
        }));
    } else {
        return false;
    }
}
usuario4815162342
fuente
2
var newObj = { a: 4, b: 0.5 , c: 0.35, d: 5 };
var maxValue = Math.max(...Object.values(newObj))
var minValue = Math.min(...Object.values(newObj))
usuario12723650
fuente
3
Al responder una pregunta anterior, su respuesta sería mucho más útil para otros usuarios de StackOverflow si incluyera algún contexto para explicar cómo ayuda su respuesta, particularmente para una pregunta que ya tiene una respuesta aceptada. Ver: ¿Cómo escribo una buena respuesta ?
David Buck
0

Esto funciona para mi:

var object = { a: 4, b: 0.5 , c: 0.35, d: 5 };
// Take all value from the object into list
var valueList = $.map(object,function(v){
     return v;
});
var max = valueList.reduce(function(a, b) { return Math.max(a, b); });
var min = valueList.reduce(function(a, b) { return Math.min(a, b); });
jaydip jadhav
fuente