Schneller Weg, um die Min / Max-Werte unter den Eigenschaften des Objekts zu erhalten

89

Ich habe ein Objekt in Javascript wie folgt:

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

Gibt es eine schnelle Möglichkeit, den minimalen und maximalen Wert zwischen den Eigenschaften zu ermitteln, ohne sie alle durchlaufen zu müssen? weil das Objekt, das ich habe, riesig ist und ich alle zwei Sekunden den Min / Max-Wert erhalten muss. (Die Werte des Objekts ändern sich ständig).

Youssef
quelle
3
@Oleg: Nun, wenn man nur das bedenkt, könnte es sehr gut JSON sein. Youssef: Analysieren Sie den JSON in ein Objekt und durchlaufen Sie seine Eigenschaften.
Felix Kling
@ OlegV.Volkov Ich benutze JSON.parse () sollte das nicht Json machen?
Youssef
@Youssef Vor dem Parsen war JSON (ein String-Wert). Es ist ein Objektwert nach dem Parsen.
Šime Vidas
2
JSON ist die String-Notation von Objekten. Wenn Sie JSON zu einem Objekt analysieren, ist es nicht mehr im JSON-Format
altschuler
1
Ich habe mir erlaubt, JSON -> Objekt in Ihrer Frage zu reparieren, da Kommentare bestätigen, dass es das ist, was Sie gemeint haben.
Oleg V. Volkov

Antworten:

18

Es gibt im allgemeinen Fall keine Möglichkeit, das Maximum / Minimum zu finden, ohne alle n Elemente zu durchlaufen (wenn Sie von 1 nach n-1 gehen, woher wissen Sie, ob das Element n nicht größer (oder kleiner) als das ist Strom max / min)?

Sie haben erwähnt, dass sich die Werte alle paar Sekunden ändern. Wenn Sie genau wissen, welche Werte sich ändern, können Sie mit Ihren vorherigen Max / Min-Werten beginnen und nur mit den neuen vergleichen. Selbst in diesem Fall können Sie dies tun, wenn einer der geänderten Werte Ihr alter Max / Min-Wert war müssen sie erneut durchlaufen.

Eine andere Alternative - wiederum nur, wenn die Anzahl der sich ändernden Werte gering ist - besteht darin, die Werte in einer Struktur wie einem Baum oder einem Heap zu speichern. Wenn die neuen Werte eintreffen, würden Sie sie entsprechend einfügen (oder aktualisieren). Aber ob Sie das können, ist anhand Ihrer Frage nicht klar.

Wenn Sie das maximale / minimale Element einer bestimmten Liste erhalten möchten, während Sie alle Elemente durchlaufen, können Sie so etwas wie das folgende Snippet verwenden, aber Sie können dies nicht tun, ohne alle Elemente durchzugehen

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];
}
carlosfigueira
quelle
2
Dies beschreibt nicht, wie die Min / Max-Werte der Eigenschaften eines Objekts abgerufen werden.
FistOfFury
131

Update: Moderne Version (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}` );


Ursprüngliche Antwort:

Versuche dies:

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

und dann:

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

Live-Demo: http://jsfiddle.net/7GCu7/1/

Šime Vidas
quelle
21
Kann auch tunmax = Object.keys(obj).reduce(function(m, k){ return obj[k] > m ? obj[k] : m }, -Infinity);
Levi
4
Kann das jetzt auch tun: Math.max(...arr);
cmac
1
@cmac Ich habe eine ES6-Version hinzugefügt.
Šime Vidas
@ ŠimeVidas - Was bedeuten die 3 Punkte in der Math.min & Max-Funktion? Vielen Dank
AME
12

minund maxmüssen trotzdem das Eingabearray durchlaufen - wie sonst würden sie das größte oder kleinste Element finden?

Eine kurze for..inSchleife funktioniert also einwandfrei.

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
quelle
1
Dies ist großartig für IE7 / 8. Cheers @Niet the Dark Absol
ojhawkins
Es ist nicht unbedingt wahr, dass Min und Max das Array durchlaufen, um ihre Werte zu erhalten. Es ist praktikabler, dass sie das Array
schnell sortieren
7
@goonerify Die schnellste Sortierung ist O(n log n), die von Natur aus langsamer ist als die O(n), die nur einmal durchgescannt werden würde ...
Niet the Dark Absol
11

Du könntest es versuchen:

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
quelle
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
quelle
1
Erklärung hinzugefügt.
Andrey Kudriavtsev
4

Sie können es auch mit versuchen 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
quelle
3

Hier ist eine Lösung, mit der Sie auch den Schlüssel zurückgeben können und nur eine Schleife ausführen. Es sortiert die Einträge des Objekts (nach Wert) und gibt dann den ersten und den letzten zurück.

Außerdem wird das sortierte Objekt zurückgegeben, das das vorhandene Objekt ersetzen kann, sodass zukünftige Sortierungen schneller sind, da es bereits halbsortiert ist = besser als O (n). Es ist wichtig zu beachten, dass Objekte ihre Reihenfolge in ES6 beibehalten.

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
quelle
Vielen Dank! Ich habe versucht herauszufinden, wie ich das Maximum erreichen kann, während ich den Schlüssel für den Wert behalte. Das hat geholfen! :)
ScamCast
2

Für verschachtelte Strukturen unterschiedlicher Tiefe {node: {leaf: 4}, leaf: 1}funktioniert dies (dh mit lodash oder Unterstrich):

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;
    }
}
user4815162342
quelle
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))
user12723650
quelle
3
Bei der Beantwortung einer alten Frage wäre Ihre Antwort für andere StackOverflow-Benutzer viel nützlicher, wenn Sie einen Kontext angeben, um zu erklären, wie Ihre Antwort hilft, insbesondere bei einer Frage, für die bereits eine Antwort akzeptiert wurde. Siehe auch : Wie kann ich eine gute Antwort schreiben .
David Buck
0

Das funktioniert bei mir:

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
quelle