javascript - मैं कैसे जांचूं कि सरणी में जावास्क्रिप्ट में कोई ऑब्जेक्ट शामिल है या नहीं?




arrays browser (25)

b मूल्य है, और a सरणी है। यह true या false देता true :

function(a, b) {
    return a.indexOf(b) != -1
}

जावास्क्रिप्ट सरणी में कोई ऑब्जेक्ट है या नहीं, यह जानने के लिए सबसे संक्षिप्त और कुशल तरीका क्या है?

यह एकमात्र तरीका है जिसे मैं जानता हूं:

function contains(a, obj) {
    for (var i = 0; i < a.length; i++) {
        if (a[i] === obj) {
            return true;
        }
    }
    return false;
}

क्या इसे पूरा करने के लिए एक बेहतर और अधिक संक्षिप्त तरीका है?

यह स्टैक ओवरफ़्लो प्रश्न से बहुत करीबी से संबंधित है जावास्क्रिप्ट ऐरे में किसी आइटम को खोजने का सबसे अच्छा तरीका? जो indexOf का उपयोग कर सरणी में ऑब्जेक्ट ढूंढने को संबोधित करता है।


उपयोग:

Array.prototype.contains = function(x){
  var retVal = -1;

  // x is a primitive type
  if(["string","number"].indexOf(typeof x)>=0 ){ retVal = this.indexOf(x);}

  // x is a function
  else if(typeof x =="function") for(var ix in this){
    if((this[ix]+"")==(x+"")) retVal = ix;
  }

  //x is an object...
  else {
    var sx=JSON.stringify(x);
    for(var ix in this){
      if(typeof this[ix] =="object" && JSON.stringify(this[ix])==sx) retVal = ix;
    }
  }

  //Return False if -1 else number if numeric otherwise string
  return (retVal === -1)?false : ( isNaN(+retVal) ? retVal : +retVal);
}

मुझे पता है कि यह जाने का सबसे अच्छा तरीका नहीं है, लेकिन चूंकि ऑब्जेक्ट्स के बीच बातचीत करने के लिए कोई मूलभूत असंभव तरीका नहीं है, मुझे लगता है कि यह करीब है क्योंकि आप एक सरणी में दो इकाइयों की तुलना कर सकते हैं। इसके अलावा, ऐरे ऑब्जेक्ट को विस्तारित करना एक बुद्धिमान काम नहीं हो सकता है, लेकिन कभी-कभी यह ठीक है (यदि आप इसके बारे में जानते हैं और व्यापार बंद हैं)।


यदि आप जावास्क्रिप्ट 1.6 या बाद में (फ़ायरफ़ॉक्स 1.5 या बाद में) का उपयोग कर रहे हैं तो आप Array.indexOf का उपयोग कर सकते हैं। अन्यथा, मुझे लगता है कि आप अपने मूल कोड के समान कुछ खत्म करने जा रहे हैं।


अपडेट करें: जैसा कि @orip टिप्पणियों में उल्लेख करता है, लिंक किए गए बेंचमार्क 2008 में किया गया था, इसलिए परिणाम आधुनिक ब्राउज़र के लिए प्रासंगिक नहीं हो सकते हैं। हालांकि, आपको संभवतः गैर-आधुनिक ब्राउज़र का समर्थन करने के लिए इसकी आवश्यकता है और संभवतया उन्हें अपडेट नहीं किया गया है। हमेशा अपने लिए परीक्षण करें।

जैसा कि अन्य ने कहा है, सरणी के माध्यम से पुनरावृत्ति शायद सबसे अच्छा तरीका है, लेकिन यह साबित हुआ है कि कम हो रहा है while लूप जावास्क्रिप्ट में पुन: प्रयास करने का सबसे तेज़ तरीका है। तो आप निम्नानुसार अपना कोड फिर से लिखना चाहेंगे:

function contains(a, obj) {
    var i = a.length;
    while (i--) {
       if (a[i] === obj) {
           return true;
       }
    }
    return false;
}

बेशक, आप ऐरे प्रोटोटाइप का विस्तार भी कर सकते हैं:

Array.prototype.contains = function(obj) {
    var i = this.length;
    while (i--) {
        if (this[i] === obj) {
            return true;
        }
    }
    return false;
}

और अब आप बस निम्न का उपयोग कर सकते हैं:

alert([1, 2, 3].contains(2)); // => true
alert([1, 2, 3].contains('2')); // => false

indexOf शायद, लेकिन यह "ईसीएमए -262 मानक के लिए जावास्क्रिप्ट एक्सटेंशन है, क्योंकि यह मानक के अन्य कार्यान्वयन में मौजूद नहीं हो सकता है।"

उदाहरण:

[1, 2, 3].indexOf(1) => 0
["foo", "bar", "baz"].indexOf("bar") => 1
[1, 2, 3].indexOf(4) => -1

AFAICS माइक्रोसॉफ्ट इस तरह के किसी प्रकार का विकल्प नहीं प्रदान करता है , लेकिन यदि आप एक त्वरित Google खोज से पता चलता है , तो आप इंटरनेट एक्सप्लोरर (और अन्य ब्राउज़र्स जो indexOf समर्थन नहीं करते हैं) में सरणी के लिए समान कार्यक्षमता जोड़ सकते हैं (उदाहरण के लिए, यह एक )।


समाधान जो सभी आधुनिक ब्राउज़रों में काम करता है:

function contains(arr, obj) {
  const stringifiedObj = JSON.stringify(obj); // Cache our object to not call `JSON.stringify` on every iteration
  return arr.some(item => JSON.stringify(item) === stringifiedObj);
}

उपयोग:

contains([{a: 1}, {a: 2}], {a: 1}); // true

आईई 6 + समाधान:

function contains(arr, obj) {
  var stringifiedObj = JSON.stringify(obj)
  return arr.some(function (item) {
    return JSON.stringify(item) === stringifiedObj;
  });
}

// .some polyfill, not needed for IE9+
if (!('some' in Array.prototype)) {
  Array.prototype.some = function (tester, that /*opt*/) {
    for (var i = 0, n = this.length; i < n; i++) {
      if (i in this && tester.call(that, this[i], i, this)) return true;
    } return false;
  };
}

उपयोग:

contains([{a: 1}, {a: 2}], {a: 1}); // true

JSON.stringify का उपयोग क्यों करें?

Array.indexOf और Array.includes (साथ ही साथ अधिकांश उत्तरों) केवल संदर्भ द्वारा तुलना करें और मूल्य से नहीं।

[{a: 1}, {a: 2}].includes({a: 1});
// false, because {a: 1} is a new object

बोनस

गैर अनुकूलित ईएस 6 एक लाइनर:

[{a: 1}, {a: 2}].some(item => JSON.stringify(item) === JSON.stringify({a: 1));
// true

नोट: मूल्यों से वस्तुओं की तुलना करना बेहतर होगा यदि कुंजी एक ही क्रम में हैं, इसलिए सुरक्षित होने के लिए आप पहले इस तरह के पैकेज के साथ चाबियाँ सॉर्ट कर सकते हैं: https://www.npmjs.com/package/sort-keys

एक perf अनुकूलन के साथ contains समारोह अद्यतन किया गया। इसे इंगित करने के लिए धन्यवाद।


वर्तमान ब्राउज़रों में Array#includes , जो वास्तव में करता है , व्यापक रूप से समर्थित है , और पुराने ब्राउज़र के लिए polyfill है।

> ['joe', 'jane', 'mary'].includes('jane');
true 

आप Array#indexOf का भी उपयोग कर सकते हैं, जो कम प्रत्यक्ष है, लेकिन पॉलीफिल को पुराने ब्राउज़र के लिए आवश्यक नहीं है।

jQuery $.inArray प्रदान करता है, जो कार्यात्मक रूप से Array#indexOf बराबर है।

underscore.js , एक जावास्क्रिप्ट उपयोगिता लाइब्रेरी, _.contains(list, value) , उपनाम _.include(list, value) , जिनमें से दोनों एक जावास्क्रिप्ट सरणी पारित होने पर आंतरिक रूप से _.include(list, value) का उपयोग करते हैं।

कुछ अन्य ढांचे समान तरीकों की पेशकश करते हैं:

ध्यान दें कि कुछ ढांचे इसे एक फ़ंक्शन के रूप में कार्यान्वित करते हैं, जबकि अन्य सरणी प्रोटोटाइप में फ़ंक्शन जोड़ते हैं।


function contains(a, obj) {
    return a.some(function(element){return element == obj;})
}

Array.prototype.some() को 5 वें संस्करण में ईसीएमए -262 मानक में जोड़ा गया था


ठीक है, आप परिणाम प्राप्त करने के लिए बस अपना कोड अनुकूलित कर सकते हैं ! ऐसा करने के कई तरीके हैं जो क्लीनर और बेहतर हैं, लेकिन मैं सिर्फ अपना पैटर्न प्राप्त करना चाहता हूं और उस पर लागू होता JSON.stringifyहूं, बस अपने मामले में ऐसा कुछ करें:

function contains(a, obj) {
    for (var i = 0; i < a.length; i++) {
        if (JSON.stringify(a[i]) === JSON.stringify(obj)) {
            return true;
        }
    }
    return false;
}

हम इस स्निपेट का उपयोग करते हैं (वस्तुओं, सरणी, तारों के साथ काम करता है):

/*
 * @function
 * @name Object.prototype.inArray
 * @description Extend Object prototype within inArray function
 *
 * @param {mix}    needle       - Search-able needle
 * @param {bool}   searchInKey  - Search needle in keys?
 *
 */
Object.defineProperty(Object.prototype, 'inArray',{
    value: function(needle, searchInKey){

        var object = this;

        if( Object.prototype.toString.call(needle) === '[object Object]' || 
            Object.prototype.toString.call(needle) === '[object Array]'){
            needle = JSON.stringify(needle);
        }

        return Object.keys(object).some(function(key){

            var value = object[key];

            if( Object.prototype.toString.call(value) === '[object Object]' || 
                Object.prototype.toString.call(value) === '[object Array]'){
                value = JSON.stringify(value);
            }

            if(searchInKey){
                if(value === needle || key === needle){
                return true;
                }
            }else{
                if(value === needle){
                    return true;
                }
            }
        });
    },
    writable: true,
    configurable: true,
    enumerable: false
});

उपयोग:

var a = {one: "first", two: "second", foo: {three: "third"}};
a.inArray("first");          //true
a.inArray("foo");            //false
a.inArray("foo", true);      //true - search by keys
a.inArray({three: "third"}); //true

var b = ["one", "two", "three", "four", {foo: 'val'}];
b.inArray("one");         //true
b.inArray('foo');         //false
b.inArray({foo: 'val'})   //true
b.inArray("{foo: 'val'}") //false

var c = "String";
c.inArray("S");        //true
c.inArray("s");        //false
c.inArray("2", true);  //true
c.inArray("20", true); //false

जबकि array.indexOf(x)!=-1 ऐसा करने का सबसे संक्षिप्त तरीका है (और गैर-इंटरनेट एक्सप्लोरर ब्राउज़र द्वारा एक दशक से अधिक समर्थित है ...), यह ओ (1) नहीं है, बल्कि ओ ( एन), जो भयानक है। यदि आपकी सरणी बदली नहीं जा रही है, तो आप अपनी सरणी को हैशटेबल में बदल सकते हैं, फिर table[x]!==undefined या ===undefined :

Array.prototype.toTable = function() {
    var t = {};
    this.forEach(function(x){t[x]=true});
    return t;
}

डेमो:

var toRemove = [2,4].toTable();
[1,2,3,4,5].filter(function(x){return toRemove[x]===undefined})

(दुर्भाग्यवश, जब आप किसी सरणी को "फ्रीज" करने के लिए Array.prototype.contains बना सकते हैं और इस पंक्ति में हैशटेबल को दो पंक्तियों में संग्रहीत करते हैं, तो यह गलत परिणाम देगा यदि आपने बाद में अपनी सरणी संपादित करना चुना है। जावास्क्रिप्ट में अपर्याप्त हुक है उदाहरण के लिए पाइथन के विपरीत, आप इस स्थिति को रखने दें।)


प्रोटोटाइप यह कैसे करता है यहां बताया गया है :

/**
 *  Array#indexOf(item[, offset = 0]) -> Number
 *  - item (?): A value that may or may not be in the array.
 *  - offset (Number): The number of initial items to skip before beginning the
 *      search.
 *
 *  Returns the position of the first occurrence of `item` within the array &mdash; or
 *  `-1` if `item` doesn't exist in the array.
**/
function indexOf(item, i) {
  i || (i = 0);
  var length = this.length;
  if (i < 0) i = length + i;
  for (; i < length; i++)
    if (this[i] === item) return i;
  return -1;
}

यह भी देखें कि वे इसे कैसे हुक करते हैं।


कोई उस Set उपयोग कर सकता है जिसमें "है ()" विधि है:

function contains(arr, obj) {
  var proxy = new Set(arr);
  if (proxy.has(obj))
    return true;
  else
    return false;
}

var arr = ['Happy', 'New', 'Year'];
console.log(contains(arr, 'Happy'));


function inArray(elem,array)
{
    var len = array.length;
    for(var i = 0 ; i < len;i++)
    {
        if(array[i] == elem){return i;}
    }
    return -1;
} 

यदि मिला तो सरणी अनुक्रमणिका लौटाता है, या -1 नहीं मिला है


जावास्क्रिप्ट Array ऑब्जेक्ट को विस्तार करना वास्तव में एक बुरा विचार है क्योंकि आप नई गुणों (आपकी कस्टम विधियों) को for-in लूप में पेश करते हैं जो मौजूदा स्क्रिप्ट को तोड़ सकते हैं। कुछ साल पहले Prototype लाइब्रेरी के लेखकों को इस तरह की चीज़ को हटाने के लिए अपने पुस्तकालय कार्यान्वयन को फिर से इंजीनियर करना था।

यदि आपको अपने पृष्ठ पर चल रहे अन्य जावास्क्रिप्ट के साथ संगतता के बारे में चिंता करने की आवश्यकता नहीं है, तो इसके लिए जाएं, अन्यथा, मैं अधिक अजीब, लेकिन सुरक्षित मुक्त-स्थायी फ़ंक्शन समाधान की अनुशंसा करता हूं।


यदि आप किसी ऑब्जेक्ट में किसी ऑब्जेक्ट के अस्तित्व के लिए बार-बार जांच कर रहे हैं तो आपको शायद देखना चाहिए

  1. सरणी को अपने सरणी में सम्मिलन प्रकार करके हर समय क्रमबद्ध करना (नई जगहें सही जगह पर रखें)
  2. वस्तुओं को अद्यतन + सॉर्ट किए गए सम्मिलन ऑपरेशन के रूप में अद्यतन करें और
  3. अपने contains(a, obj) में एक बाइनरी खोज लुकअप का प्रयोग करें।

एक सेकंड के लिए बॉक्स से बाहर सोचकर, यदि आप कई बार यह कॉल कर रहे हैं, तो एक हैश फ़ंक्शन का उपयोग करके लुकअप करने के लिए एक सहयोगी सरणी का उपयोग करने के लिए यह अधिक कुशल है।

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map


Array.indexOf का जावास्क्रिप्ट 1.6 संगत कार्यान्वयन Array.indexOf :

if (!Array.indexOf)
{
  Array.indexOf = [].indexOf ?
      function (arr, obj, from) { return arr.indexOf(obj, from); }:
      function (arr, obj, from) { // (for IE6)
        var l = arr.length,
            i = from ? parseInt( (1*from) + (from<0 ? l:0), 10) : 0;
        i = i<0 ? 0 : i;
        for (; i<l; i++) {
          if (i in arr  &&  arr[i] === obj) { return i; }
        }
        return -1;
      };
}

ईसीएमएस्क्रिप्ट 6 में खोजने पर एक शानदार प्रस्ताव है।

खोज विधि सरणी में मौजूद प्रत्येक तत्व के लिए एक बार कॉलबैक फ़ंक्शन निष्पादित करती है जब तक कि उसे कोई ऐसा नहीं मिलता जहां कॉलबैक एक वास्तविक मान देता है। यदि ऐसा कोई तत्व पाया जाता है, तो तत्काल उस तत्व का मान वापस प्राप्त करें। अन्यथा, रिटर्न अपरिभाषित खोजें। कॉलबैक केवल सरणी के इंडेक्स के लिए लगाया जाता है जिसने मूल्य आवंटित किए हैं; यह उन इंडेक्स के लिए नहीं बुलाया जाता है जिन्हें हटा दिया गया है या जिन्हें कभी मूल्य नहीं दिया गया है।

यहां पर एमडीएन दस्तावेज है।

खोज कार्यक्षमता इस तरह काम करती है।

function isPrime(element, index, array) {
    var start = 2;
    while (start <= Math.sqrt(element)) {
        if (element % start++ < 1) return false;
    }
    return (element > 1);
}

console.log( [4, 6, 8, 12].find(isPrime) ); // Undefined, not found
console.log( [4, 5, 8, 12].find(isPrime) ); // 5

आप इस कार्य को परिभाषित करके ECMAScript 5 और नीचे में इसका उपयोग कर सकते हैं।

if (!Array.prototype.find) {
  Object.defineProperty(Array.prototype, 'find', {
    enumerable: false,
    configurable: true,
    writable: true,
    value: 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++) {
        if (i in list) {
          value = list[i];
          if (predicate.call(thisArg, value, i, list)) {
            return value;
          }
        }
      }
      return undefined;
    }
  });
}

आप इस चाल का भी उपयोग कर सकते हैं:

var arrayContains = function(object) {
  return (serverList.filter(function(currentObject) {
    if (currentObject === object) {
      return currentObject
    }
    else {
      return false;
    }
  }).length > 0) ? true : false
}

शीर्ष उत्तरों आदिम प्रकार मानते हैं, लेकिन यदि आप यह जानना चाहते हैं कि किसी सरणी में कुछ विशेषता वाले ऑब्जेक्ट हैं, तो Array.prototype.some() एक बहुत ही सुरुचिपूर्ण समाधान है:

const items = [ {a: '1'}, {a: '2'}, {a: '3'} ]

items.some(item => item.a === '3')  // returns true
items.some(item => item.a === '4')  // returns false

इसके बारे में अच्छी बात यह है कि तत्व मिलने के बाद पुनरावृत्ति को निरस्त कर दिया जाता है ताकि अनावश्यक पुनरावृत्ति चक्र बचाए जा सकें।

साथ ही, यह एक बयान में अच्छी तरह से फिट बैठता है क्योंकि यह एक बूलियन देता है:

if (items.some(item => item.a === '3')) {
  // do something
}

* जैसे ही जेम्स ने टिप्पणी में बताया, सितंबर 2018 के रूप में, Array.prototype.some() पूरी तरह से समर्थित है: caniuse.com समर्थन तालिका


Lodash के some समारोह का प्रयोग करें।

यह संक्षेप में, सटीक और महान क्रॉस प्लेटफ़ॉर्म समर्थन है।

स्वीकार्य उत्तर आवश्यकताओं को पूरा नहीं करता है।

आवश्यकताएं: यह पता लगाने के लिए सबसे संक्षिप्त और कुशल तरीका सुझाएं कि जावास्क्रिप्ट सरणी में कोई ऑब्जेक्ट है या नहीं।

स्वीकृत उत्तर:

$.inArray({'b': 2}, [{'a': 1}, {'b': 2}])
> -1

मेरी सिफारिश:

_.some([{'a': 1}, {'b': 2}], {'b': 2})
> true

टिप्पणियाँ:

$ .inArray यह निर्धारित करने के लिए ठीक काम करता है कि स्केलर की एक सरणी में स्केलर मान मौजूद है या नहीं ...

$.inArray(2, [1,2])
> 1

... लेकिन सवाल स्पष्ट रूप से यह निर्धारित करने के लिए एक कुशल तरीका मांगता है कि कोई ऑब्जेक्ट किसी सरणी में निहित है या नहीं।

दोनों scalars और वस्तुओं को संभालने के लिए, आप यह कर सकते हैं:

(_.isObject(item)) ? _.some(ary, item) : (_.indexOf(ary, item) > -1)

जैसा कि अन्य ने उल्लेख किया है कि आप इसका उपयोग कर सकते हैं Array.indexOf, लेकिन यह सभी ब्राउज़रों में उपलब्ध नहीं है। यहां https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf से कोड पुराने ब्राउज़र में समान बनाने के लिए है।

इंडेक्सऑफ ईसीएमए -262 मानक के लिए हालिया जोड़ा है; क्योंकि यह सभी ब्राउज़रों में मौजूद नहीं हो सकता है। आप अपनी स्क्रिप्ट की शुरुआत में निम्न कोड डालने के द्वारा इस पर काम कर सकते हैं, जिससे इंडेक्स का उपयोग कार्यान्वयन में किया जा सकता है जो इसे मूल रूप से समर्थन नहीं देता है। यह एल्गोरिदम वास्तव में ईसीएमए -262, 5 वें संस्करण में निर्दिष्ट है, ऑब्जेक्ट, टाइप एरर, संख्या, Math.floor, Math.abs, और Math.max को मानते हुए उनका मूल मान है।

if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
        "use strict";
        if (this == null) {
            throw new TypeError();
        }
        var t = Object(this);
        var len = t.length >>> 0;
        if (len === 0) {
            return -1;
        }
        var n = 0;
        if (arguments.length > 1) {
            n = Number(arguments[1]);
            if (n != n) { // shortcut for verifying if it's NaN
                n = 0;
            } else if (n != 0 && n != Infinity && n != -Infinity) {
                n = (n > 0 || -1) * Math.floor(Math.abs(n));
            }
        }
        if (n >= len) {
            return -1;
        }
        var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
        for (; k < len; k++) {
            if (k in t && t[k] === searchElement) {
                return k;
            }
        }
        return -1;
    }
}

किसी प्रकार के वैध समाधान एकत्र करने के लिए:

var stringVariable = "some text";
var findString = "text";

//using `indexOf()`
var containResult1 = stringVariable.indexOf(findString) != -1;
document.write(containResult1+', ');

//using `lastIndexOf()`
var containResult2 = stringVariable.lastIndexOf(findString) != -1;
document.write(containResult2+', ');

//using `search()`
var containResult3 = stringVariable.search(findString) != -1;
document.write(containResult3+', ');
     
//using `split()`
var containResult4 = stringVariable.split(findString)[0] != stringVariable;
document.write(containResult4+'');





javascript arrays browser