Cách nhanh chóng để nhận các giá trị tối thiểu / tối đa giữa các thuộc tính của đối tượng


93

Tôi có một đối tượng trong javascript như thế này:

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

Có cách nào nhanh chóng để nhận giá trị nhỏ nhất và lớn nhất trong số các thuộc tính mà không cần phải lặp lại tất cả chúng không? vì đối tượng tôi có rất lớn và tôi cần nhận giá trị tối thiểu / tối đa hai giây một lần. (Các giá trị của đối tượng liên tục thay đổi).


3
@Oleg: Chà, chỉ có điều này, nó rất có thể là JSON. Youssef: Phân tích cú pháp JSON thành một đối tượng và lặp lại các thuộc tính của nó.
Felix Kling

@ OlegV.Volkov Tôi đang sử dụng JSON.parse () nên không phải là Json?
Youssef

@Youssef Đó là JSON (là một giá trị Chuỗi) trước khi phân tích cú pháp. Đó là một giá trị Đối tượng sau khi phân tích cú pháp.
Šime Vidas

2
JSON là ký hiệu chuỗi của các đối tượng. Khi bạn phân tích cú pháp JSON để một đối tượng, nó không còn trong JSON định dạng
altschuler

1
Tôi đã tự do sửa đối tượng JSON -> trong câu hỏi của bạn, vì các nhận xét xác nhận rằng đó là ý bạn.
Oleg V. Volkov

Câu trả lời:


19

Không có cách nào để tìm giá trị lớn nhất / tối thiểu trong trường hợp tổng quát mà không lặp lại tất cả n phần tử (nếu bạn đi từ 1 đến n-1, làm cách nào để bạn biết liệu n phần tử không lớn hơn (hoặc nhỏ hơn) tối đa hiện tại / phút)?

Bạn đã đề cập rằng các giá trị thay đổi sau vài giây. Nếu bạn biết chính xác giá trị nào thay đổi, bạn có thể bắt đầu với giá trị tối đa / tối thiểu trước đó và chỉ so sánh với giá trị mới, nhưng ngay cả trong trường hợp này, nếu một trong các giá trị đã được sửa đổi là giá trị tối đa / tối thiểu cũ của bạn, bạn có thể cần lặp lại chúng một lần nữa.

Một cách thay thế khác - một lần nữa, chỉ khi số lượng giá trị thay đổi ít - sẽ là lưu trữ các giá trị trong một cấu trúc như cây hoặc một đống và khi các giá trị mới đến, bạn sẽ chèn (hoặc cập nhật) chúng một cách thích hợp. Nhưng liệu bạn có thể làm điều đó hay không thì không rõ ràng dựa trên câu hỏi của bạn.

Nếu bạn muốn nhận phần tử tối đa / tối thiểu của một danh sách nhất định trong khi lặp qua tất cả các phần tử, thì bạn có thể sử dụng một cái gì đó như đoạn mã bên dưới, nhưng bạn sẽ không thể làm điều đó nếu không xem qua tất cả chúng

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
Điều này không mô tả cách lấy giá trị tối thiểu / tối đa của các thuộc tính của một đối tượng.
FistOfFury

Bạn đang lặp qua một đối tượng, không phải một danh sách. minmaxkhông xác định. Ý bạn là sử dụng một for invòng lặp để thay thế?
tonix

1
Cảm ơn @tonix, đã sửa nó.
carlosfigueira

138

Cập nhật: Phiên bản hiện đại (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}` );


Câu trả lời gốc:

Thử đi:

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

và sau đó:

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

Bản demo trực tiếp: http://jsfiddle.net/7GCu7/1/


21
Cũng có thể làmmax = Object.keys(obj).reduce(function(m, k){ return obj[k] > m ? obj[k] : m }, -Infinity);
levi

4
Cũng có thể làm điều này ngay bây giờ: Math.max(...arr);
cmac 17/02/17

1
@cmac Tôi đã thêm phiên bản ES6.
Šime Vidas

@ ŠimeVidas - 3 dấu chấm trên hàm Math.min & max đại diện cho điều gì? Cảm ơn
AME


12

minmaxvẫn phải lặp qua mảng đầu vào - bằng cách nào khác họ sẽ tìm phần tử lớn nhất hoặc nhỏ nhất?

Vì vậy, chỉ cần một for..invòng lặp nhanh sẽ hoạt động tốt.

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
Điều này rất tốt cho IE7 / 8. Cheers @Niet the Dark Absol
ojhawkins.

Không nhất thiết phải đúng rằng min và max lặp qua mảng để nhận các giá trị của chúng.
Khả

7
@goonerify Loại nhanh nhất là O(n log n), vốn dĩ đã chậm hơn so với loại O(n)chỉ quét qua một lần sẽ là ...
Niet the Dark Absol

11

Bạn có thể thử:

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
Đã thêm giải thích.
Andrey Kudriavtsev

4

Bạn cũng có thể thử với 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

Đây là một giải pháp cho phép bạn trả lại khóa và chỉ thực hiện một vòng lặp. Nó sắp xếp các mục nhập của Đối tượng (theo val) và sau đó trả về mục nhập đầu tiên và cuối cùng.

Ngoài ra, nó trả về Đối tượng đã được sắp xếp có thể thay thế Đối tượng hiện có để việc sắp xếp trong tương lai sẽ nhanh hơn vì nó đã được sắp xếp một nửa = tốt hơn O (n). Điều quan trọng cần lưu ý là các Đối tượng giữ nguyên thứ tự của chúng trong 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));


Cảm ơn! Tôi đang cố gắng tìm ra cách để đạt được giá trị tối đa trong khi vẫn giữ lại chìa khóa để đi với giá trị. Điều này đã giúp! :)
010011100101

2

Đối với các cấu trúc lồng nhau có độ sâu khác nhau, tức là {node: {leaf: 4}, leaf: 1}, điều này sẽ hoạt động (sử dụng dấu gạch ngang hoặc dấu gạch dưới):

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
Khi trả lời một câu hỏi cũ, câu trả lời của bạn sẽ hữu ích hơn nhiều đối với những người dùng StackOverflow khác nếu bạn đưa vào một số ngữ cảnh để giải thích câu trả lời của bạn giúp ích như thế nào, đặc biệt đối với một câu hỏi đã có câu trả lời được chấp nhận. Xem: Làm thế nào để tôi viết một câu trả lời tốt .
David Buck

0

Điều này phù hợp với tôi:

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); });
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.