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).


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

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/


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

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

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

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);



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));


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

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))

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); });
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.