Швидкий спосіб отримати значення min / max серед властивостей об’єкта


93

У мене є такий об’єкт у javascript:

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

Чи існує швидкий спосіб отримати мінімальне та максимальне значення серед властивостей, не маючи необхідності прокручувати їх усі? оскільки об’єкт у мене величезний, і мені потрібно отримувати мінімальне / максимальне значення кожні дві секунди. (Значення об’єкта постійно змінюються).


3
@Oleg: Ну, враховуючи лише це, цілком може бути JSON. Юсеф: Проаналізуйте JSON на об'єкт і перегляньте його властивості.
Фелікс Клінг,

@ OlegV.Volkov Я використовую JSON.parse (), чи не слід це зробити Json?
Юсеф,

@Youssef Це був JSON (що є значенням String) перед синтаксичним аналізом. Це значення об’єкта після аналізу.
Шіме Відас,

2
JSON - це рядковий запис об'єктів. Коли ви аналізуєте JSON на об'єкт, він перестає бути у форматі JSON
altschuler

1
Я дозволив собі виправити об’єкт JSON -> у вашому запитанні, оскільки коментарі підтверджують, що це саме те, що ви мали на увазі.
Олег Васильович Волков,

Відповіді:


19

Немає способу знайти максимум / мінімум у загальному випадку, не переглядаючи всі n елементів (якщо перейти від 1 до n-1, як дізнатись, чи не є елемент n більшим (чи меншим), ніж поточний макс / хв)?

Ви згадали, що значення змінюються кожні пару секунд. Якщо ви точно знаєте, які значення змінюються, ви можете почати з попередніх значень max / min і порівняти лише з новими, але навіть у цьому випадку, якщо одним із значень, які було змінено, було ваше старе значення max / min, ви можете потрібно ще раз прокрутити їх.

Іншою альтернативою - знову ж таки, лише якщо кількість значень, які змінюються, є невеликою - було б зберігати значення у такій структурі, як дерево або куча, і по мірі надходження нових значень ви б вставляли (або оновлювали) їх належним чином. Але чи можете ви це зробити, на підставі вашого запитання не зрозуміло.

Якщо ви хочете отримати максимальний / мінімальний елемент даного списку, переглядаючи всі елементи, тоді ви можете використовувати щось на зразок фрагмента нижче, але ви не зможете цього зробити, не пройшовши всі

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
Це не описує, як отримати мінімальне / максимальне значення властивостей об’єкта.
FistOfFury

Ви перебираєте об’єкт, а не список. minі maxне визначені. Ви хотіли for inзамість цього використовувати цикл?
tonix

1
Дякую @tonix, виправив.
carlosfigueira

138

Оновлення: Сучасна версія (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}` );


Оригінальна відповідь:

Спробуйте це:

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

і потім:

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

Демо-версія: http://jsfiddle.net/7GCu7/1/


21
Можна такожmax = Object.keys(obj).reduce(function(m, k){ return obj[k] > m ? obj[k] : m }, -Infinity);
levi

4
Це можна зробити і зараз: Math.max(...arr);
cmac

1
@cmac Я додав версію ES6.
Шіме Відас,

@ ŠimeVidas - що представляють 3 крапки у функції Math.min & max? Дякую
AME


12

minі maxвсе одно доведеться прокручувати вхідний масив - як інакше вони знайдуть найбільший чи найменший елемент?

Тож лише швидкий for..inцикл буде справно працювати.

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
Це чудово для IE7 / 8. Вітаємо @Niet the Dark
Absol

Необов’язково вірно, що min та max проходять через масив, щоб отримати їх значення. Більш доцільно, щоб вони
швидко сортували

7
@goonerify Найшвидше сортування O(n log n), яке за своєю суттю повільніше, ніж те, O(n)що було б просто сканувати один раз ...
Niet the Dark Absol

11

Ви можете спробувати:

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
Пояснення додано.
Андрій Кудрявцев

4

Ви також можете спробувати 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

Ось рішення, яке дозволяє повернути ключ, а також лише один цикл. Він сортує записи об’єкта (за значенням val), а потім повертає перший і останній.

Крім того, він повертає відсортований Об’єкт, який може замінити існуючий Об’єкт, так що майбутні сортування будуть швидшими, оскільки він вже буде напівсортуваний = кращий за O (n). Важливо зазначити, що об’єкти зберігають свій порядок у 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));


Дякую! Я намагався зрозуміти, як отримати максимум, зберігаючи при цьому ключ, який відповідає значенню. Це допомогло! :)
010011100101

2

Для вкладених структур різної глибини, тобто {node: {leaf: 4}, leaf: 1}це буде працювати (використовуючи лодаш або підкреслення):

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
Відповідаючи на старе запитання, ваша відповідь була б набагато кориснішою для інших користувачів StackOverflow, якщо ви включили якийсь контекст, щоб пояснити, як допомагає ваша відповідь, особливо на питання, яке вже має прийняту відповідь. Дивіться: Як написати хорошу відповідь .
Девід Бак,

0

Це працює для мене:

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); });
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.