วิธีที่รวดเร็วในการรับค่าต่ำสุด / สูงสุดระหว่างคุณสมบัติของวัตถุ


94

ฉันมีวัตถุในจาวาสคริปต์เช่นนี้:

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

มีวิธีที่รวดเร็วในการรับค่าต่ำสุดและสูงสุดระหว่างคุณสมบัติโดยไม่ต้องวนซ้ำทั้งหมดหรือไม่? เนื่องจากวัตถุที่ฉันมีมีขนาดใหญ่และฉันต้องได้รับค่าต่ำสุด / สูงสุดทุกๆสองวินาที (ค่าของวัตถุเปลี่ยนแปลงไปเรื่อย ๆ )


3
@ โอเล็ก: เอาแค่นี้มันอาจเป็น JSON ได้เป็นอย่างดี Youssef: แยกวิเคราะห์ JSON เป็นออบเจ็กต์และวนซ้ำคุณสมบัติของมัน
Felix Kling

@ OlegV.Volkov ฉันใช้ JSON.parse () นั่นไม่ควรทำให้เป็น Json?
Youssef

@Youssef มันคือ JSON (ซึ่งเป็นค่าสตริง) ก่อนที่จะแยกวิเคราะห์ เป็นค่า Object หลังจากแยกวิเคราะห์
Šime Vidas

2
JSON คือสัญกรณ์สตริงของอ็อบเจ็กต์ เมื่อคุณแยกวิเคราะห์ JSON ไปยังวัตถุจะไม่อยู่ในรูปแบบ JSON อีกต่อไป
altschuler

1
ฉันมีเสรีภาพในการแก้ไขวัตถุ JSON -> ในคำถามของคุณเนื่องจากความคิดเห็นยืนยันว่าเป็นสิ่งที่คุณหมายถึง
Oleg V. Volkov

คำตอบ:


19

ไม่มีทางที่จะหาค่าสูงสุด / ต่ำสุดในกรณีทั่วไปโดยไม่ต้องวนซ้ำองค์ประกอบnทั้งหมด(ถ้าคุณเปลี่ยนจาก 1 เป็น n-1 คุณจะรู้ได้อย่างไรว่าองค์ประกอบnไม่ใหญ่ (หรือเล็กกว่า) กว่า สูงสุด / นาทีปัจจุบัน)?

คุณบอกว่าค่าต่างๆจะเปลี่ยนไปทุก ๆ สองวินาที หากคุณทราบแน่ชัดว่าค่าใดเปลี่ยนแปลงคุณสามารถเริ่มต้นด้วยค่าสูงสุด / นาทีก่อนหน้าและเปรียบเทียบกับค่าใหม่เท่านั้น แต่ในกรณีนี้หากค่าใดค่าหนึ่งที่แก้ไขเป็นค่าสูงสุด / นาทีเก่าของคุณคุณอาจ ต้องวนซ้ำอีกครั้ง

อีกทางเลือกหนึ่ง - อีกครั้งเฉพาะในกรณีที่จำนวนค่าที่เปลี่ยนแปลงมีขนาดเล็กจะเป็นการจัดเก็บค่าในโครงสร้างเช่นทรีหรือฮีปและเมื่อค่าใหม่มาถึงคุณจะต้องแทรก (หรืออัปเดต) อย่างเหมาะสม แต่คุณสามารถทำได้หรือไม่นั้นไม่ชัดเจนตามคำถามของคุณ

หากคุณต้องการรับองค์ประกอบสูงสุด / ต่ำสุดของรายการที่กำหนดในขณะที่วนลูปผ่านองค์ประกอบทั้งหมดคุณสามารถใช้บางอย่างเช่นข้อมูลโค้ดด้านล่าง แต่คุณจะไม่สามารถทำได้หากไม่ผ่านองค์ประกอบทั้งหมด

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

139

อัปเดต: เวอร์ชันทันสมัย ​​(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 แล้ว
Šime Vidas

@ Š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 Cheers @Niet the Dark Absol
ojhawkins

ไม่จำเป็นว่าขั้นต่ำและสูงสุดจะวนรอบอาร์เรย์เพื่อรับค่า เป็นไปได้มากกว่าที่พวกเขาจะจัดเรียงอาร์เรย์อย่างรวดเร็วและเลือกค่าต่ำสุดและสูงสุดตามผลลัพธ์นั้น
goonerify

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
เพิ่มคำอธิบายแล้ว
Andrey Kudriavtsev



3

นี่เป็นวิธีแก้ปัญหาที่ช่วยให้คุณสามารถคืนคีย์ได้เช่นกันและทำเพียงลูปเดียวเท่านั้น จัดเรียงรายการของวัตถุ (ตามค่า) แล้วส่งกลับรายการแรกและรายการสุดท้าย

นอกจากนี้ยังส่งคืน Object ที่จัดเรียงซึ่งสามารถแทนที่ Object ที่มีอยู่เพื่อให้การเรียงลำดับในอนาคตเร็วขึ้นเนื่องจากจะถูกจัดเรียงแบบกึ่ง = ดีกว่า O (n) อยู่แล้ว สิ่งสำคัญคือต้องทราบว่า Objects จะรักษาลำดับของมันใน 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}จะได้ผล (โดยใช้ lodash หรือขีดล่าง):

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 คนอื่น ๆ หากคุณรวมบริบทบางส่วนเพื่ออธิบายว่าคำตอบของคุณช่วยได้อย่างไรโดยเฉพาะสำหรับคำถามที่มีคำตอบที่ยอมรับแล้ว ดู: ฉันจะเขียนคำตอบที่ดีได้อย่างไร
David Buck

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); });
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.