Maneira rápida de obter os valores mínimo / máximo entre as propriedades do objeto


90

Tenho um objeto em javascript como este:

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

Existe uma maneira rápida de obter o valor mínimo e máximo entre as propriedades sem ter que percorrer todos eles? porque o objeto que tenho é enorme e preciso obter o valor mínimo / máximo a cada dois segundos. (Os valores do objeto continuam mudando).


3
@Oleg: Bem, considerando apenas isso, poderia muito bem ser JSON. Youssef: analise o JSON em um objeto e itere sobre suas propriedades.
Felix Kling

@ OlegV.Volkov Estou usando JSON.parse () não deveria ser Json?
Youssef

@Youssef Era JSON (que é um valor String) antes da análise. É um valor de objeto após a análise.
Šime Vidas

2
JSON é a notação de string de objetos. Quando você analisa JSON para um objeto, ele não está mais no formato JSON
altschuler

1
Tomei a liberdade de corrigir o objeto JSON -> em sua pergunta, pois os comentários confirmam que é isso que você quis dizer.
Oleg V. Volkov

Respostas:


19

Não há como encontrar o máximo / mínimo no caso geral sem percorrer todos os n elementos (se você for de 1 para n-1, como saber se o elemento n não é maior (ou menor) que o máx / min atual)?

Você mencionou que os valores mudam a cada dois segundos. Se você sabe exatamente quais valores mudam, você pode começar com seus valores máx. / Mín. Anteriores e apenas comparar com os novos, mas mesmo neste caso, se um dos valores que foram modificados era o antigo máx. / Mín., Você pode precisa percorrê-los novamente.

Outra alternativa - novamente, apenas se o número de valores que mudam for pequeno - seria armazenar os valores em uma estrutura como uma árvore ou um heap e, conforme os novos valores chegam, você os insere (ou atualiza) apropriadamente. Mas se você pode fazer isso, não fica claro com base em sua pergunta.

Se você deseja obter o elemento máximo / mínimo de uma determinada lista enquanto percorre todos os elementos, então você pode usar algo como o snippet abaixo, mas não será capaz de fazer isso sem passar por todos eles

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

2
Isso não descreve como obter os valores mínimo / máximo das propriedades de um objeto.
FistOfFury

133

Atualização: versão 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}` );


Resposta Original:

Experimente isto:

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

e depois:

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

Demonstração ao vivo: http://jsfiddle.net/7GCu7/1/


21
Também posso fazermax = Object.keys(obj).reduce(function(m, k){ return obj[k] > m ? obj[k] : m }, -Infinity);
levi de

4
Também posso fazer isso agora: Math.max(...arr);
cmac

1
@cmac Eu adicionei uma versão ES6.
Šime Vidas de

@ ŠimeVidas - o que representam os 3 pontos na função Math.min e max? Obrigado
AME


12

mine maxter que percorrer a matriz de entrada de qualquer maneira - de que outra forma eles encontrariam o maior ou o menor elemento?

Portanto, apenas um for..inloop rápido funcionará bem.

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
Isso é ótimo para o IE7 / 8. Cheers @Niet the Dark Absol
ojhawkins

Não é necessariamente verdade que mínimo e máximo percorrem a matriz para obter seus valores. É mais viável que eles classifiquem rapidamente a matriz e selecionem os valores mínimo e máximo com base nesse resultado
goonerify

7
@goonerify O tipo mais rápido é O(n log n), que é inerentemente mais lento do O(n)que apenas escanear uma vez seria ...
Niet the Dark Absol

11

Você poderia tentar:

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
Explicação adicionada.
Andrey Kudriavtsev

4

Você também pode tentar com 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

Aqui está uma solução que permite que você retorne a chave também e faça apenas um loop. Ele classifica as entradas do objeto (por val) e retorna a primeira e a última.

Além disso, ele retorna o Objeto classificado que pode substituir o Objeto existente para que as classificações futuras sejam mais rápidas porque já estará semi-classificado = melhor que O (n). É importante observar que os Objetos mantêm sua ordem no 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));


Obrigado! Eu estava tentando descobrir como obter o máximo e ainda manter a chave para acompanhar o valor. Isso ajudou! :)
010011100101

2

Para estruturas aninhadas de profundidade diferente, ou seja {node: {leaf: 4}, leaf: 1}, isso funcionará (usando lodash ou sublinhado):

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

1
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
Ao responder a uma pergunta antiga, sua resposta seria muito mais útil para outros usuários do StackOverflow se você incluísse algum contexto para explicar como sua resposta ajuda, especialmente para uma pergunta que já tem uma resposta aceita. Veja: Como escrevo uma boa resposta .
David Buck

0

Isso funciona para mim:

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); });
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.