Un modo veloce per ottenere i valori min / max tra le proprietà dell'oggetto


94

Ho un oggetto in javascript come questo:

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

Esiste un modo rapido per ottenere il valore minimo e massimo tra le proprietà senza doverle scorrere tutte? perché l'oggetto che ho è enorme e devo ottenere il valore min / max ogni due secondi. (I valori dell'oggetto continuano a cambiare).


3
@Oleg: Beh, dato solo questo, potrebbe benissimo essere JSON. Youssef: analizza il JSON in un oggetto e itera sulle sue proprietà.
Felix Kling

@ OlegV.Volkov Sto usando JSON.parse () non dovrebbe renderlo Json?
Youssef

@Youssef Era JSON (che è un valore String) prima dell'analisi. È un valore Object dopo l'analisi.
Šime Vidas

2
JSON è la notazione di stringa degli oggetti. Quando analizzi JSON su un oggetto, non è più nel formato JSON
altschuler

1
Mi sono preso la libertà di correggere JSON -> oggetto nella tua domanda, poiché i commenti confermano che è quello che intendevi.
Oleg V. Volkov

Risposte:


19

Non c'è modo di trovare il massimo / minimo nel caso generale senza scorrere tutti gli n elementi (se vai da, 1 a n-1, come fai a sapere se l'elemento n non è più grande (o più piccolo) del corrente max / min)?

Hai detto che i valori cambiano ogni paio di secondi. Se sai esattamente quali valori cambiano, puoi iniziare con i tuoi valori max / min precedenti e confrontarli solo con quelli nuovi, ma anche in questo caso, se uno dei valori che sono stati modificati era il tuo vecchio max / min, puoi è necessario ripeterli nuovamente.

Un'altra alternativa - ancora una volta, solo se il numero di valori che cambiano è piccolo - sarebbe quella di memorizzare i valori in una struttura come un albero o un mucchio, e quando arrivano i nuovi valori dovresti inserirli (o aggiornarli) in modo appropriato. Ma se puoi farlo non è chiaro in base alla tua domanda.

Se vuoi ottenere l'elemento massimo / minimo di un dato elenco mentre scorri tutti gli elementi, puoi usare qualcosa come lo snippet qui sotto, ma non sarai in grado di farlo senza esaminarli tutti

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
Questo non descrive come ottenere i valori min / max delle proprietà di un oggetto.
FistOfFury

Stai iterando su un oggetto, non su un elenco. mine maxsono indefiniti. Intendevi for ininvece usare un loop?
tonix

1
Grazie @tonix, risolto.
carlosfigueira,

139

Aggiornamento: versione 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}` );


Risposta originale:

Prova questo:

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

e poi:

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

Demo dal vivo: http://jsfiddle.net/7GCu7/1/


21
Può anche faremax = Object.keys(obj).reduce(function(m, k){ return obj[k] > m ? obj[k] : m }, -Infinity);
levi

4
Può anche farlo ora: Math.max(...arr);
cmac

1
@cmac ho aggiunto una versione ES6.
Šime Vidas

@ ŠimeVidas - cosa rappresentano i 3 punti sulla funzione Math.min e max? Grazie
AME


12

mine maxdevono comunque scorrere l'array di input - in quale altro modo potrebbero trovare l'elemento più grande o più piccolo?

Quindi solo un for..inciclo veloce funzionerà perfettamente.

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
Questo è ottimo per IE7 / 8. Cheers @Niet the Dark Absol
ojhawkins

Non è necessariamente vero che min e max passano in rassegna l'array per ottenere i loro valori. È più fattibile che ordinino rapidamente l'array e selezionino i valori minimo e massimo in base a quel risultato
goonerify

7
@goonerify Il tipo più veloce è O(n log n), che è intrinsecamente più lento di quello O(n)che una sola scansione sarebbe ...
Niet the Dark Absol

11

Potresti provare:

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
Spiegazione aggiunta.
Andrey Kudriavtsev

4

Puoi anche provare 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

Ecco una soluzione che ti consente di restituire anche la chiave e fa solo un ciclo. Ordina le voci dell'oggetto (per val) e quindi restituisce la prima e l'ultima.

Inoltre, restituisce l'oggetto ordinato che può sostituire l'oggetto esistente in modo che gli ordinamenti futuri saranno più veloci perché sarà già semi-ordinato = migliore di O (n). È importante notare che gli oggetti mantengono il loro ordine in 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));


Grazie! Stavo cercando di capire come ottenere il massimo pur mantenendo la chiave per andare con il valore. Questo ha aiutato! :)
010011100101

2

Per strutture annidate di diversa profondità, vale a dire {node: {leaf: 4}, leaf: 1}, questo funzionerà (usando lodash o underscore):

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
Quando rispondi a una vecchia domanda, la tua risposta sarebbe molto più utile per gli altri utenti StackOverflow se includessi un contesto per spiegare come la tua risposta aiuta, in particolare per una domanda che ha già una risposta accettata. Vedi: come scrivo una buona risposta .
David Buck,

0

Questo funziona per me:

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); });
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.