न्यूनतम / अधिकतम प्राप्त करने के लिए वस्तुओं के जावास्क्रिप्ट ऐरे की तुलना करें


95

मेरे पास वस्तुओं की एक सरणी है और मैं उन वस्तुओं की तुलना किसी विशिष्ट वस्तु संपत्ति पर करना चाहता हूं। यहाँ मेरी सरणी है:

var myArray = [
    {"ID": 1, "Cost": 200},
    {"ID": 2, "Cost": 1000},
    {"ID": 3, "Cost": 50},
    {"ID": 4, "Cost": 500}
]

मैं विशेष रूप से "लागत" पर शून्य करना चाहता हूं और एक मिनट और अधिकतम मूल्य प्राप्त करना चाहता हूं। मुझे लगता है कि मैं केवल लागत मूल्यों को पकड़ सकता हूं और उन्हें एक जावास्क्रिप्ट सरणी में धकेल सकता हूं और फिर फास्ट जावास्क्रिप्ट मैक्स / मिनट चला सकता हूं ।

हालाँकि, बीच में ऐरो स्टेप को दरकिनार कर और ऑब्जेक्ट्स प्रॉपर्टीज (इस मामले में "कॉस्ट") को सीधे करने का एक आसान तरीका है?

जवाबों:


53

इस मामले में सबसे तेज़ तरीका, सभी तत्वों के माध्यम से लूपिंग है, और अब तक के उच्चतम / निम्नतम मूल्य से इसकी तुलना करें।

(एक सरणी बनाना, इस सरल ऑपरेशन के लिए सरणी विधियों को लागू करना ओवरकिल है)।

 // There's no real number bigger than plus Infinity
var lowest = Number.POSITIVE_INFINITY;
var highest = Number.NEGATIVE_INFINITY;
var tmp;
for (var i=myArray.length-1; i>=0; i--) {
    tmp = myArray[i].Cost;
    if (tmp < lowest) lowest = tmp;
    if (tmp > highest) highest = tmp;
}
console.log(highest, lowest);

यह समझ में आता है, मैं बाहरी उच्च / निम्न संख्या के बजाय सरणी के अंदर डेटा की एक-दूसरे से तुलना करने के बारे में सोचकर फंस गया हूं।

1
केवल एक चीज जो मैं बदलूंगा वह है सबसे कम सेट करना और सबसे अधिक थोड़ा बेमानी। मैं नहीं बल्कि एक कम समय पाश और सेट होगा lowest=highest=myArray[0]और उसके बाद 1. पर पाश शुरू
जे होम्स

1
@ 32 बिटकॉइन अच्छी बात है। myArray[0].Costहालांकि होना चाहिए । लेकिन, अगर कोई पहला तत्व नहीं है, तो एक त्रुटि डाली जाएगी। तो, एक अतिरिक्त जांच की आवश्यकता है, संभवतः छोटे प्रदर्शन को बढ़ावा देने के लिए।
रॉब डब्ल्यू

मैं यहां आया क्योंकि मैं चाहता हूं कि वस्तु खुद लौट आए। न्यूनतम मूल्य नहीं, जो आसान था। कोई सुझाव?
विल्ट

1
@ हाँ, एक और वैरिएबल बनाए रखें जो तब अपडेट होता है जब आपने सबसे कम मूल्य पाया है, var lowestObject; for (...)औरif (tmp < lowest) { lowestObject = myArray[i]; lowest = tmp; }
रोब डब्ल्यू

163

इस तरह से सामान के लिए कम करना अच्छा है: वस्तुओं की एक सरणी पर कुल संचालन (जैसे मिनट, अधिकतम, औसत, आदि) करने के लिए और एकल परिणाम लौटाएं:

myArray.reduce(function(prev, curr) {
    return prev.Cost < curr.Cost ? prev : curr;
});

... या आप ES6 फ़ंक्शन सिंटैक्स के साथ उस आंतरिक फ़ंक्शन को परिभाषित कर सकते हैं:

(prev, curr) => prev.Cost < curr.Cost ? prev : curr

यदि आप प्यारा होना चाहते हैं, तो आप इसे सरणी से जोड़ सकते हैं:

Array.prototype.hasMin = function(attrib) {
    return (this.length && this.reduce(function(prev, curr){ 
        return prev[attrib] < curr[attrib] ? prev : curr; 
    })) || null;
 }

अब आप कह सकते हैं:

myArray.hasMin('ID')  // result:  {"ID": 1, "Cost": 200}
myArray.hasMin('Cost')    // result: {"ID": 3, "Cost": 50}
myEmptyArray.hasMin('ID')   // result: null

कृपया ध्यान दें कि यदि आप इसे इस्तेमाल करने का इरादा रखते हैं, तो इसमें हर स्थिति के लिए पूरी जाँच नहीं है। यदि आप आदिम प्रकारों की एक सरणी में पास करते हैं, तो यह विफल हो जाएगा। यदि आप ऐसी संपत्ति की जाँच करते हैं जो मौजूद नहीं है, या यदि सभी वस्तुओं में वह संपत्ति नहीं है, तो आपको अंतिम तत्व मिलेगा। यह संस्करण थोड़ा अधिक भारी है, लेकिन उन जाँचों में है:

Array.prototype.hasMin = function(attrib) {
    const checker = (o, i) => typeof(o) === 'object' && o[i]
    return (this.length && this.reduce(function(prev, curr){
        const prevOk = checker(prev, attrib);
        const currOk = checker(curr, attrib);
        if (!prevOk && !currOk) return {};
        if (!prevOk) return curr;
        if (!currOk) return prev;
        return prev[attrib] < curr[attrib] ? prev : curr; 
    })) || null;
 }

14
मेरी राय में सबसे अच्छा जवाब। यह सरणी को और इसके उत्तर को अधिक संक्षिप्त रूप में संशोधित नहीं करता है जो कहता है कि "एक सरणी बनाना, सरणी विधियों को लागू करना इस सरल ऑपरेशन के लिए ओवरकिल है"
जूलियन मान

बड़े डेटासेट (30+ कॉलम / 100k पंक्तियों) के प्रदर्शन के लिए यह सबसे अच्छा उत्तर है।
CERD

2
सोच रहा था, जब चेक कम हो जाता है तो सरणी का पहला तत्व prev.Costअपरिभाषित नहीं होगा? या यह 0 के रूप में आरंभ करता है?
ग्रेवडॉक्स

1
अच्छी बात @ साहेब। मैंने अभी संपादित किया है इसलिए यह उस स्थिति में अशक्त हो जाएगा।
त्रिस्टान रीड

1
मैंने अन्य इनपुटों के लिए कुछ चेक भी जोड़े, जो समस्या का कारण बन सकते हैं, जैसे गैर-ऑब्जेक्ट, या यदि वह संपत्ति कुछ वस्तुओं से गायब थी। अंततः मुझे लगता है कि ज्यादातर मामलों के लिए थोड़ा भारी हाथ मिल रहा है।
ट्रिस्टन रीड

26

उपयोग करें sort, यदि आप सरणी के संशोधित होने की परवाह नहीं करते हैं।

myArray.sort(function (a, b) {
    return a.Cost - b.Cost
})

var min = myArray[0],
    max = myArray[myArray.length - 1]

3
एक पूर्ण प्रकार न्यूनतम / अधिकतम खोजने का सबसे तेज़ तरीका नहीं है, लेकिन मुझे लगता है कि यह काम करेगा।
जे। होम्स

4
बस ध्यान रखें कि यह संशोधित होगा myArray, जिसकी उम्मीद नहीं की जा सकती है।
ज़ीसेमर

किसी सरणी को छांटना, उसे ट्रेस करने की तुलना में धीमा है। क्रमबद्धता को क्रमबद्ध करें: O(nlog(n))एक सरणी का पता O(n)
लगाना

18

Mathफ़ंक्शंस का उपयोग करें और उन मूल्यों को प्लक करें जो आप चाहते हैंmap

यहाँ jsbin है:

https://jsbin.com/necosu/1/edit?js,console

var myArray = [{
    "ID": 1,
    "Cost": 200
  }, {
    "ID": 2,
    "Cost": 1000
  }, {
    "ID": 3,
    "Cost": 50
  }, {
    "ID": 4,
    "Cost": 500
  }],

  min = Math.min.apply(null, myArray.map(function(item) {
    return item.Cost;
  })),
  max = Math.max.apply(null, myArray.map(function(item) {
    return item.Cost;
  }));

console.log('min', min);//50
console.log('max', max);//1000

अपडेट करें:

यदि आप ES6 का उपयोग करना चाहते हैं:

var min = Math.min.apply(null, myArray.map(item => item.Cost)),
    max = Math.max.apply(null, myArray.map(item => item.Cost));

15
स्प्रेड ऑपरेटर का उपयोग करते हुए ES6 में, हमें अब आवश्यकता नहीं है apply। सीधे शब्दों में कहें - Math.min(...myArray.map(o => o.Cost))न्यूनतम Math.max(...myArray.map(o => o.Cost))खोजने के लिए और अधिकतम खोजने के लिए।
नितिन

13

मुझे लगता है कि रोब डब्ल्यू का जवाब वास्तव में सही है (+1), लेकिन सिर्फ मनोरंजन के लिए: यदि आप "चतुर" बनना चाहते थे, तो आप ऐसा कुछ कर सकते हैं:

var myArray = 
[
    {"ID": 1, "Cost": 200},
    {"ID": 2, "Cost": 1000},
    {"ID": 3, "Cost": 50},
    {"ID": 4, "Cost": 500}
]

function finder(cmp, arr, attr) {
    var val = arr[0][attr];
    for(var i=1;i<arr.length;i++) {
        val = cmp(val, arr[i][attr])
    }
    return val;
}

alert(finder(Math.max, myArray, "Cost"));
alert(finder(Math.min, myArray, "Cost"));

या यदि आपके पास एक गहरी नेस्टेड संरचना थी, तो आप थोड़ा अधिक कार्यात्मक हो सकते हैं और निम्नलिखित कार्य कर सकते हैं:

var myArray = 
[
    {"ID": 1, "Cost": { "Wholesale":200, Retail: 250 }},
    {"ID": 2, "Cost": { "Wholesale":1000, Retail: 1010 }},
    {"ID": 3, "Cost": { "Wholesale":50, Retail: 300 }},
    {"ID": 4, "Cost": { "Wholesale":500, Retail: 1050 }}
]

function finder(cmp, arr, getter) {
    var val = getter(arr[0]);
    for(var i=1;i<arr.length;i++) {
        val = cmp(val, getter(arr[i]))
    }
    return val;
}

alert(finder(Math.max, myArray, function(x) { return x.Cost.Wholesale; }));
alert(finder(Math.min, myArray, function(x) { return x.Cost.Retail; }));

ये आसानी से अधिक उपयोगी / विशिष्ट रूपों में करी जा सकती हैं।


4
मैंने हमारे समाधानों को बेंचमार्क किया है: jsperf.com/comparison-of-numbers । अपने कोड को अनुकूलित करने के बाद (बेंचमार्क देखें), दोनों तरीकों का प्रदर्शन समान है। अनुकूलन के बिना, मेरी विधि 14x तेज है।
रॉब डब्ल्यू

2
@RoBW ओह मैं पूरी तरह से अपने संस्करण होने की अपेक्षा करेंगे जिस तरह से तेजी से, मैं सिर्फ एक वैकल्पिक वास्तु कार्यान्वयन प्रदान किया गया था। :)
जे। होम्स

@ 32 बिटकॉइन से मुझे भी यही उम्मीद थी, लेकिन हैरानी की बात यह है कि यह तरीका लगभग उतना ही तेज है (अनुकूलन के बाद), जैसा कि बेंचमार्क के टेस्ट केस 3 में देखा गया है।
रॉब डब्ल्यू

1
@ रोब मैं सहमत हूँ, मुझे उम्मीद नहीं थी कि। मेरे साथ षड्यंत्र रचा गया। :) यह दिखाने के लिए जाता है कि आपको हमेशा मान लेने के बजाय बेंचमार्क करना चाहिए।
जे। होम्स

@RobW बस स्पष्ट होने के लिए, मुझे लगता है कि अधिक ब्राउज़र परिणामों के साथ, आपका क्रियान्वयन निरंतर या तो अनधिकृत और अनुकूलित संस्करणों को हरा देगा।
जे। होम्स


5

प्रयास करें ( aसरणी है, fतुलना करने के लिए फ़ील्ड है)

let max= (a,f)=> a.reduce((m,x)=> m[f]>x[f] ? m:x);
let min= (a,f)=> a.reduce((m,x)=> m[f]<x[f] ? m:x);


2
इस जवाब से प्यार है, इसलिए कॉम्पैक्ट और उपयोग करने में आसान है।
डीन

3

Array.prototype.reduce () का उपयोग करके , आप एक सरणी में न्यूनतम, अधिकतम, आदि आइटम को निर्धारित करने के लिए तुलनित्र कार्यों में प्लग कर सकते हैं।

var items = [
  { name : 'Apple',  count : 3  },
  { name : 'Banana', count : 10 },
  { name : 'Orange', count : 2  },
  { name : 'Mango',  count : 8  }
];

function findBy(arr, key, comparatorFn) {
  return arr.reduce(function(prev, curr, index, arr) { 
    return comparatorFn.call(arr, prev[key], curr[key]) ? prev : curr; 
  });
}

function minComp(prev, curr) {
  return prev < curr;
}

function maxComp(prev, curr) {
  return prev > curr;
}

document.body.innerHTML  = 'Min: ' + findBy(items, 'count', minComp).name + '<br />';
document.body.innerHTML += 'Max: ' + findBy(items, 'count', maxComp).name;


3

उपयोग करना Math.minऔर Math.max:

var myArray = [
    { id: 1, cost: 200},
    { id: 2, cost: 1000},
    { id: 3, cost: 50},
    { id: 4, cost: 500}
]


var min = Math.min(...myArray.map(item => item.cost));
var max = Math.max(...myArray.map(item => item.cost));

console.log("min: " + min);
console.log("max: " + max);


2

यह अधिक बेहतर उपाय है

    var myArray = [
    {"ID": 1, "Cost": 200},
    {"ID": 2, "Cost": 1000},
    {"ID": 3, "Cost": 50},
    {"ID": 4, "Cost": 500}
    ]
    var lowestNumber = myArray[0].Cost;
    var highestNumber = myArray[0].Cost;

    myArray.forEach(function (keyValue, index, myArray) {
      if(index > 0) {
        if(keyValue.Cost < lowestNumber){
          lowestNumber = keyValue.Cost;
        }
        if(keyValue.Cost > highestNumber) {
          highestNumber = keyValue.Cost;
        }
      }
    });
    console.log('lowest number' , lowestNumber);
    console.log('highest Number' , highestNumber);

2

ट्रिस्टन रीड के उत्तर (+ es6 का उपयोग करके) को जोड़कर, आप एक फ़ंक्शन बना सकते हैं जो कॉलबैक स्वीकार करता है, जिसमें वह ऑपरेटर होगा जिसे आप लागू करना चाहते हैं prevऔर curr:

const compare = (arr, key, callback) => arr.reduce((prev, curr) =>
    (callback(prev[key], curr[key]) ? prev : curr), {})[key];

    // remove `[key]` to return the whole object

तो आप बस का उपयोग कर कॉल कर सकते हैं:

const costMin = compare(myArray, 'Cost', (a, b) => a < b);
const costMax = compare(myArray, 'Cost', (a, b) => a > b);

2

यह लॉश के कार्यों minByऔर maxByकार्यों के साथ प्राप्त किया जा सकता है ।

लोदाश minByऔर maxByप्रलेखन

_.minBy(array, [iteratee=_.identity])

_.maxBy(array, [iteratee=_.identity])

ये विधियां एक पुनरावृति को स्वीकार करती हैं, जो कि मान को रैंक करने वाले मानदंड को उत्पन्न करने के लिए प्रत्येक तत्व के लिए लागू किया जाता है। पुनरावृति को एक तर्क के साथ लागू किया जाता है: (मान)।

उपाय

var myArray = [
    {"ID": 1, "Cost": 200},
    {"ID": 2, "Cost": 1000},
    {"ID": 3, "Cost": 50},
    {"ID": 4, "Cost": 500}
]

const minimumCostItem = _.minBy(myArray, "Cost");

console.log("Minimum cost item: ", minimumCostItem);

// Getting the maximum using a functional iteratee
const maximumCostItem = _.maxBy(myArray, function(entry) {
  return entry["Cost"];
});

console.log("Maximum cost item: ", maximumCostItem);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>


0

हम समस्या को दो दृष्टिकोण से हल कर सकते हैं दोनों विधि पहले से ही ऊपर बताई गई है लेकिन प्रदर्शन परीक्षण इतना पूरा नहीं था

1, देशी जावा-स्क्रिप्ट तरीका
2, पहले सॉर्ट ऑब्जेक्ट फिर सॉर्ट किए गए ओबज से न्यूनतम अधिकतम प्राप्त करना आसान है

मैं भी दोनों टो दृष्टिकोण के प्रदर्शन का परीक्षण

आप भी चला सकते हैं और प्रदर्शन का परीक्षण कर सकते हैं ... हैप्पी कोडिंग (:

//first approach 

var myArray = [
    {"ID": 1, "Cost": 200},
    {"ID": 2, "Cost": 1000},
    {"ID": 3, "Cost": 50},
    {"ID": 4, "Cost": 500}
]

var t1 = performance.now();;

let max=Math.max.apply(Math, myArray.map(i=>i.Cost))

let min=Math.min.apply(Math, myArray.map(i=>i.Cost))

var t2   = performance.now();;

console.log("native fuction took " + (t2 - t1) + " milliseconds.");

console.log("max Val:"+max)
console.log("min Val:"+min)

//  Second approach:


function sortFunc (a, b) {
    return a.Cost - b.Cost
} 

var s1 = performance.now();;
sortedArray=myArray.sort(sortFunc)


var minBySortArray = sortedArray[0],
    maxBySortArray = sortedArray[myArray.length - 1]
    
var s2   = performance.now();;
 console.log("sort funciton took  " + (s2 - s1) + " milliseconds.");  
console.log("max ValBySortArray :"+max)
console.log("min Val BySortArray:"+min)


0

संक्षिप्त, आधुनिक समाधान के लिए, कोई reduceसरणी पर एक ऑपरेशन कर सकता है , वर्तमान न्यूनतम और अधिकतम मानों पर नज़र रख सकता है, इसलिए सरणी केवल एक बार (जो कि इष्टतम है) पर पुनरावृत्त होती है।

let [min, max] = myArray.reduce(([prevMin,prevMax], {Cost})=>
   [Math.min(prevMin, Cost), Math.max(prevMax, Cost)], [Infinity, -Infinity]);

डेमो:


-2

केनेबेक के उत्तर के समान एक और एक, लेकिन सभी एक पंक्ति में:

maxsort = myArray.slice(0).sort(function (a, b) { return b.ID - a.ID })[0].ID; 

-2

आप इसके बजाय Math.max / Math.min का उपयोग करने के लिए अंतर्निहित Array ऑब्जेक्ट का उपयोग कर सकते हैं:

var arr = [1,4,2,6,88,22,344];

var max = Math.max.apply(Math, arr);// return 344
var min = Math.min.apply(Math, arr);// return 1
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.