जावास्क्रिप्ट में बूलियन स्थिति से मेल खाने वाले सरणी का पहला तत्व कैसे खोजें?


219

मुझे आश्चर्य हो रहा है कि किसी दिए गए शर्त से मेल खाने वाले JS सरणी के पहले तत्व को खोजने के लिए एक ज्ञात, अंतर्निहित / सुरुचिपूर्ण तरीका है। AC # समतुल्य होगा List.Find

अब तक मैं इस तरह से दो-फंक्शन कॉम्बो का उपयोग कर रहा हूं:

// Returns the first element of an array that satisfies given predicate
Array.prototype.findFirst = function (predicateCallback) {
    if (typeof predicateCallback !== 'function') {
        return undefined;
    }

    for (var i = 0; i < arr.length; i++) {
        if (i in this && predicateCallback(this[i])) return this[i];
    }

    return undefined;
};

// Check if element is not undefined && not null
isNotNullNorUndefined = function (o) {
    return (typeof (o) !== 'undefined' && o !== null);
};

और फिर मैं उपयोग कर सकता हूं:

var result = someArray.findFirst(isNotNullNorUndefined);

लेकिन चूंकि ECMAScript में बहुत सारे फंक्शनल-स्टाइल ऐरे मेथड हैं , शायद वहाँ पहले से ही ऐसा कुछ है? मुझे लगता है कि बहुत से लोगों को हर समय इस तरह से सामान को लागू करना पड़ता है ...


6
वहाँ बिल्ट इन मेथड नहीं है, लेकिन यूटिलिटी लाइब्रेरियाँ हैं जो इस कार्यक्षमता को अनुमानित करती हैं जैसे कि documentcloud.github.com/underscore
kinakuta

वास्तव में बहुत अच्छा लग रहा है! और यह मिल गया है ()। धन्यवाद!
याकूब पी।

1
बस इतना पता है, आप इसे कम कर सकते हैं: इसके लिए return (typeof (o) !== 'undefined' && o !== null);नीचे return o != null;। वे बिल्कुल समकक्ष हैं।
पागलपन की चट्टानें

1
जानकार अच्छा लगा। लेकिन आप जानते हैं, मैं जोर-जबरदस्ती करने वाले ऑपरेटरों को पसंद करता हूं! = या ==। मैं इसे आसानी से परख भी नहीं पाऊंगा, क्योंकि मुझे किसी भी तरह यह जांचने की आवश्यकता होगी कि उस फैशन में अशक्त होने के लिए कोई और मूल्य नहीं है ... :) तो मैं एक पुस्तकालय के लिए कितना भाग्यशाली हूं कि इसकी अनुमति है मुझे उस समारोह को पूरी तरह से हटाने के लिए ... :)
जकूब पी।

मैं ईमानदारी से यह एक काफी सुंदर समाधान कहना होगा। निकटतम चीज जो मैं पा सकता हूं वह है Array.prototype.some जो यह खोजने की कोशिश करता है कि क्या कोई तत्व किसी दिए गए शर्त को पूरा करता है जिसे आप फ़ंक्शन के रूप में पास करते हैं। दुर्भाग्य से, यह सूचकांक या तत्व के बजाय एक बूलियन देता है। मैं पुस्तकालय का उपयोग करने के बारे में आपके समाधान की सिफारिश करूंगा क्योंकि पुस्तकालय बहुत बड़े होते हैं और इसमें वे चीजें होती हैं जिनका आप उपयोग नहीं करेंगे और मैं चीजों को हल्का रखना पसंद करता हूं (क्योंकि आप केवल एक फ़ंक्शन का उपयोग कर सकते हैं जो इसे प्रदान करता है)।
ग्राहम रॉबर्टसन

जवाबों:


218

ES6 के बाद से सरणियों के लिए मूल findविधि है; यह पहला मैच खोजने के बाद सरणी को एन्यूमरेट करता है और मान लौटाता है।

const result = someArray.find(isNotNullNorUndefined);

पुराना उत्तर:

मुझे इन filterसुझावों को रोकने के लिए एक उत्तर पोस्ट करना होगा :-)

चूंकि ECMAScript में बहुत सारी कार्यात्मक-शैली की सरणी विधियाँ हैं, शायद वहाँ कुछ इस तरह से पहले से ही है?

आप someसरणी को पुनरावृत्त करने के लिए ऐरे विधि का उपयोग कर सकते हैं जब तक कि कोई शर्त पूरी न हो जाए (और फिर बंद हो जाए)। दुर्भाग्य से यह केवल यह लौटेगा कि क्या शर्त एक बार मिली थी, न कि किस तत्व (या किस सूचकांक में) से मिली थी। इसलिए हमें इसमें थोड़ा संशोधन करना होगा:

function find(arr, test, ctx) {
    var result = null;
    arr.some(function(el, i) {
        return test.call(ctx, el, i, arr) ? ((result = el), true) : false;
    });
    return result;
}

var result = find(someArray, isNotNullNorUndefined);

28
यह नहीं कह सकता कि मैं पूरी तरह से फिल्टर () पर निर्देशित नापसंद को समझता हूं। यह धीमा हो सकता है, लेकिन वास्तव में; अधिकांश मामलों में जहां यह संभवतः उपयोग किया जाता है, यह शुरुआत करने के लिए एक छोटी सूची है, और जावास्क्रिप्ट अनुप्रयोगों के अधिकांश इस स्तर पर दक्षता के बारे में वास्तव में चिंता करने के लिए पर्याप्त जटिल नहीं हैं। [] .फिल्टर (परीक्षण) .Pop () या [] .फिल्टर (परीक्षण) [0] सरल, मूल और पठनीय हैं। बेशक मैं व्यावसायिक ऐप या वेबसाइटों के बारे में बात कर रहा हूं जो गहन ऐप नहीं हैं जैसे कि गेम।
जोश मैक

11
क्या फ़िल्टर समाधान सभी सरणी / संग्रहों को पार करता है? यदि ऐसा है, तो फ़िल्टर करना बहुत अक्षम है, क्योंकि यह सभी सरणी पर चलता है, भले ही संग्रह में पहला मूल्य हो। some()दूसरी ओर, तुरंत वापस आ जाता है, जो समाधानों को छानने की तुलना में लगभग सभी मामलों में बहुत तेज है।
एलिकएल्ज़िन-किलाका

@ AlikElzin-kilaka: हां, बिल्कुल।
बरगी

15
@JoshMc यकीन है, लेकिन यह समझ में नहीं आता है कि स्टैक ओवरफ्लो जैसी सरल समस्या का समाधान पोस्ट करते समय गंभीर रूप से अक्षम नहीं होना चाहिए। बहुत से लोग यहां से एक उपयोगिता फ़ंक्शन में कोड को कॉपी और पेस्ट करेंगे, और उनमें से कुछ बिंदु पर, उस उपयोगिता फ़ंक्शन का उपयोग उस संदर्भ में करेंगे जहां निष्पादन कार्यान्वयन के बारे में सोचने के बिना प्रदर्शन मायने रखता है। यदि आपने उन्हें ऐसा कुछ दिया है जिसे शुरू करने के लिए एक कुशल कार्यान्वयन है, तो आपने या तो एक प्रदर्शन समस्या को हल किया है, जो अन्यथा उनके पास नहीं है, या उन्हें निदान करने वाले देव समय का एक गुच्छा बचाया है।
मार्क अमेरी सिप

1
@SuperUberDuper: नहीं। नीचे मार्क Amery का जवाब देखें।
बरगी

104

ECMAScript 6 के रूप में, आप इसके लिए उपयोग कर सकते हैं Array.prototype.find। यह फ़ायरफ़ॉक्स (25.0), क्रोम (45.0), एज (12), और सफारी (7.1) में लागू और काम कर रहा है, लेकिन इंटरनेट एक्सप्लोरर या अन्य पुराने या असामान्य प्लेटफार्मों का एक गुच्छा नहीं है

उदाहरण के लिए, नीचे दी गई अभिव्यक्ति का मूल्यांकन करता है 106

[100,101,102,103,104,105,106,107,108,109].find(function (el) {
    return el > 105;
});

यदि आप अभी इसका उपयोग करना चाहते हैं, लेकिन IE या अन्य असमर्थित ब्राउज़रों के लिए समर्थन की आवश्यकता है, तो आप एक शिम का उपयोग कर सकते हैं। मैं es6-shim की सलाह देता हूं । MDN एक शिम भी प्रदान करता है यदि किसी कारण से आप संपूर्ण es6-shim को अपनी परियोजना में नहीं रखना चाहते हैं। अधिकतम अनुकूलता के लिए आप es6- शिम चाहते हैं, क्योंकि MDN संस्करण के विपरीत यह बग्गी देशी कार्यान्वयन का पता लगाता है findऔर उन्हें अधिलेखित कर देता है (टिप्पणी देखें जो "Array में बग्स के आसपास काम करना शुरू करना # ढूंढना और Array # findIndex" और इसके तुरंत बाद वाली पंक्तियाँ) ।


findतब से बेहतर है जब किसी तत्व को स्थिति से मेल खाने के तुरंत filterबाद findरोक दिया जाता है, जबकि filterसभी तत्वों के माध्यम से सभी मिलान तत्वों को देता है।
एएन ट्रान

59

फ़िल्टर का उपयोग करने और परिणामी सरणी से पहला सूचकांक प्राप्त करने के बारे में क्या ?

var result = someArray.filter(isNotNullNorUndefined)[0];

6
Es5 विधियों का उपयोग करते रहें। var result = someArray.filter (isNotNullNorUndefined) .shift ();
someyoungideas

हालांकि मैं खुद @Bergi के ऊपर उत्तर खोजने के लिए मतदान करता हूं, मुझे लगता है कि ES6 विनाशकारी के साथ हम थोड़ा सुधार कर सकते हैं: var [परिणाम] = someArray.filter (isNotNullNorUndefined);
नकुल मनचंदा

@someyoungideas आप .shiftयहाँ पर उपयोग करने के लाभ की व्याख्या कर सकते हैं?
जकुबिसज़ोन

3
@jakubiszon का उपयोग करने shiftका लाभ यह है कि यह "स्मार्ट दिखता है" लेकिन वास्तव में अधिक भ्रमित है। कौन यह सोचेगा कि shift()बिना किसी तर्क के साथ कॉल करना पहला तत्व लेने के समान होगा? यह अस्पष्ट IMO है। ऐरे पहुंच वैसे भी तेज है: jsperf.com/array-access-vs-shift
जोश एम।

इसके अलावा, ES5 AFAIK में दोनों ऑब्जेक्ट्स और सरणियों के लिए वर्गाकार ब्रैकेट नोटेशन उपलब्ध है, कभी .shift()भी [0]स्पष्ट रूप से इस बारे में स्पष्टता नहीं दी गई है । इसके बावजूद, यह एक ऐसा विकल्प है जिसका आप उपयोग कर सकते हैं या नहीं, मैं [0]हालांकि इसके साथ रहना चाहूंगा ।
सिडऑफ

15

यह अब तक स्पष्ट हो जाना चाहिए कि जावास्क्रिप्ट मूल रूप से ऐसा कोई समाधान नहीं प्रदान करता है; यहाँ निकटतम दो व्युत्पन्न हैं, सबसे पहले उपयोगी:

  1. Array.prototype.some(fn)किसी शर्त के पूरा होने पर रुकने का वांछित व्यवहार प्रदान करता है, लेकिन एक तत्व मौजूद है या नहीं; कुछ प्रवंचनाओं को लागू करना कठिन नहीं है, जैसे कि बर्गी के उत्तर द्वारा प्रस्तुत समाधान ।

  2. Array.prototype.filter(fn)[0]एक महान एक-लाइनर के लिए बनाता है, लेकिन कम से कम कुशल है, क्योंकि आप N - 1तत्वों को फेंक देते हैं जो आपको चाहिए।

जावास्क्रिप्ट में पारंपरिक खोज विधियों को तत्व के बजाय तत्व के सूचकांक को वापस करने की विशेषता है या -1। यह सभी संभावित प्रकारों के डोमेन से वापसी मूल्य चुनने से बचता है; एक सूचकांक केवल एक संख्या हो सकती है और नकारात्मक मान अमान्य हैं।

ऊपर दिए गए दोनों समाधान खोज का समर्थन नहीं करते हैं, इसलिए मैंने इसे लिखने का फैसला किया है:

(function(ns) {
  ns.search = function(array, callback, offset) {
    var size = array.length;

    offset = offset || 0;
    if (offset >= size || offset <= -size) {
      return -1;
    } else if (offset < 0) {
      offset = size - offset;
    }

    while (offset < size) {
      if (callback(array[offset], offset, array)) {
        return offset;
      }
      ++offset;
    }
    return -1;
  };
}(this));

search([1, 2, NaN, 4], Number.isNaN); // 2
search([1, 2, 3, 4], Number.isNaN); // -1
search([1, NaN, 3, NaN], Number.isNaN, 2); // 3

सबसे व्यापक जवाब की तरह लग रहा है। क्या आप अपने उत्तर में तीसरा दृष्टिकोण जोड़ सकते हैं?
मृगफुल

13

सारांश:

  • एक सरणी में पहला तत्व खोजने के लिए जो बूलियन स्थिति से मेल खाता है हम उपयोग कर सकते हैं ES6 find()
  • find()पर स्थित है, Array.prototypeइसलिए इसका उपयोग हर ऐरे पर किया जा सकता है।
  • find()एक कॉलबैक लेता है जहां एक booleanशर्त का परीक्षण किया जाता है। फ़ंक्शन मान लौटाता है (इंडेक्स नहीं!)

उदाहरण:

const array = [4, 33, 8, 56, 23];

const found = array.find((element) => {
  return element > 50;
});

console.log(found);   //  56


8

यदि आप उपयोग कर रहे हैं तो आप underscore.jsइसके findऔर indexOfकार्यों का उपयोग कर सकते हैं ताकि आप जो चाहें प्राप्त कर सकें:

var index = _.indexOf(your_array, _.find(your_array, function (d) {
    return d === true;
}));

प्रलेखन:


यदि आवश्यक हो तो अंडरस्कोरज विकल्प का उपयोग करें क्योंकि इसके लिए सिर्फ एक पुस्तकालय लोड करें इसके लायक नहीं है
DannyFeliz

4

ईएस 2015 के अनुसार, Array.prototype.find()यह सटीक कार्यक्षमता प्रदान करता है।

इस सुविधा का समर्थन नहीं करने वाले ब्राउज़र के लिए, मोज़िला डेवलपर नेटवर्क ने एक पॉलीफ़िल (नीचे चिपकाया गया) प्रदान की है:

if (!Array.prototype.find) {
  Array.prototype.find = function(predicate) {
    if (this === null) {
      throw new TypeError('Array.prototype.find called on null or undefined');
    }
    if (typeof predicate !== 'function') {
      throw new TypeError('predicate must be a function');
    }
    var list = Object(this);
    var length = list.length >>> 0;
    var thisArg = arguments[1];
    var value;

    for (var i = 0; i < length; i++) {
      value = list[i];
      if (predicate.call(thisArg, value, i, list)) {
        return value;
      }
    }
    return undefined;
  };
}


2
foundElement = myArray[myArray.findIndex(element => //condition here)];

3
एक शर्त खंड और कुछ व्याख्यात्मक शब्दों के साथ एक वास्तविक जीवन का उदाहरण आपके उत्तर को अधिक मूल्यवान और समझने योग्य बना देगा।
सासचाम Sas

0

मुझे नीचे दिए गए समाधान में प्राप्त करने के लिए इंटरनेट पर कई स्रोतों से प्रेरणा मिली है। कुछ डिफ़ॉल्ट मूल्य को ध्यान में रखना और एक सामान्य दृष्टिकोण के लिए प्रत्येक प्रविष्टि की तुलना करने का एक तरीका प्रदान करना चाहता था जो यह हल करता है।

उपयोग: (मूल्य दे "दूसरा")

var defaultItemValue = { id: -1, name: "Undefined" };
var containers: Container[] = [{ id: 1, name: "First" }, { id: 2, name: "Second" }];
GetContainer(2).name;

कार्यान्वयन:

class Container {
    id: number;
    name: string;
}

public GetContainer(containerId: number): Container {
  var comparator = (item: Container): boolean => {
      return item.id == containerId;
    };
    return this.Get<Container>(this.containers, comparator, this.defaultItemValue);
  }

private Get<T>(array: T[], comparator: (item: T) => boolean, defaultValue: T): T {
  var found: T = null;
  array.some(function(element, index) {
    if (comparator(element)) {
      found = element;
      return true;
    }
  });

  if (!found) {
    found = defaultValue;
  }

  return found;
}

-2

इस खोज को करने के लिए जावास्क्रिप्ट में कोई अंतर्निहित कार्य नहीं है।

यदि आप jQuery का उपयोग कर रहे हैं तो आप कर सकते हैं a jQuery.inArray(element,array)


यह भी काम करेगा, हालांकि, मैं अंडरस्कोर शायद साथ जाऊँगा :)
जैकब पी।

3
यह पूछने वाले की आवश्यकता के उत्पादन को संतुष्ट नहीं करता है (कुछ सूचकांक में तत्व की आवश्यकता है, बूलियन नहीं)।
ग्राहम रॉबर्टसन

@GrahamRobertson $.inArrayएक बूलियन वापस नहीं करता है, यह (आश्चर्यजनक रूप से!) पहले मिलान तत्व का सूचकांक लौटाता है। यह अभी भी नहीं करता है कि ओपी के लिए क्या पूछा, यद्यपि।
मार्क अमेरी

-2

एक कम सुरुचिपूर्ण तरीका जो throwसभी सही त्रुटि संदेश (पर आधारित Array.prototype.filter) होगा, लेकिन पहला परिणाम होने पर इसे रोकना होगा

function findFirst(arr, test, context) {
    var Result = function (v, i) {this.value = v; this.index = i;};
    try {
        Array.prototype.filter.call(arr, function (v, i, a) {
            if (test(v, i, a)) throw new Result(v, i);
        }, context);
    } catch (e) {
        if (e instanceof Result) return e;
        throw e;
    }
}

फिर उदाहरण हैं

findFirst([-2, -1, 0, 1, 2, 3], function (e) {return e > 1 && e % 2;});
// Result {value: 3, index: 5}
findFirst([0, 1, 2, 3], 0);               // bad function param
// TypeError: number is not a function
findFirst(0, function () {return true;}); // bad arr param
// undefined
findFirst([1], function (e) {return 0;}); // no match
// undefined

यह filterउपयोग करके समाप्त हो जाता है throw

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.