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




प्रपत्र एचटीएमएल (20)

ECMAScript 7 array.includes(value) प्रस्तुत array.includes(value)

इसका इस्तेमाल इस तरह किया जा सकता है:

[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false

यह fromIndex वैकल्पिक दूसरा तर्क भी स्वीकार करता है:

[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true

SameValueZero विपरीत, जो सख्त समानता तुलना का उपयोग करता है, includes समान SameValueZero समानता एल्गोरिदम का उपयोग करके तुलना includes है। इसका मतलब है कि आप यह पता लगा सकते हैं कि किसी सरणी में NaN शामिल है या नहीं:

[1, 2, NaN].includes(NaN); // true

indexOf विपरीत, includes लापता सूचकांक भी नहीं छोड़े गए हैं:

new Array(5).includes(undefined); // true

वर्तमान में यह अभी भी एक मसौदा है लेकिन इसे सभी ब्राउज़रों पर काम करने के लिए polyfill किया जा सकता है।

https://code.i-harness.com

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

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

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

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

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


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)

ईसीएमएस्क्रिप्ट 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;
    }
  });
}

उपयोग:

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);
}

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



एक लाइन:

function contains(arr, x) {
    return arr.filter(function(elem) { return elem == x }).length > 0;
}

कोई उस 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'));

जबकि 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.prototype.contains = function (v) {
    return this.indexOf(v) > -1;
}

var a = [ 'foo', 'bar' ];

a.contains('foo'); // true
a.contains('fox'); // false

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

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

वर्तमान ब्राउज़रों में 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) का उपयोग करते हैं।

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

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


शीर्ष उत्तरों आदिम प्रकार मानते हैं, लेकिन यदि आप यह जानना चाहते हैं कि किसी सरणी में कुछ विशेषता वाले ऑब्जेक्ट हैं, तो 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 समर्थन तालिका


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

/*
 * @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(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;
}

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


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;
      };
}

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

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

वैकल्पिक रूप से एक तेजी से तेजी से lastIndexOf indexOf / lastIndexOf वैकल्पिक विकल्प

2015

जबकि नई विधि array.includes(value) बहुत अच्छा array.includes(value) है, समर्थन अब मूल रूप से शून्य है।

यह लंबे समय से है कि मैं धीमे इंडेक्सऑफ / lastIndexOf कार्यों को बदलने के तरीके के बारे में सोच रहा था।

शीर्ष उत्तरों को देखते हुए, एक कलाकार तरीका पहले से ही पाया जा चुका है। उन लोगों से मैंने @Damir Zekic द्वारा पोस्ट किए गए फ़ंक्शन को चुना है जो सबसे तेज़ होना चाहिए। लेकिन यह भी कहता है कि बेंचमार्क 2008 से हैं और इसलिए पुराने हैं।

मैं इसके लिए भी पसंद करता हूं, लेकिन एक विशिष्ट कारण के लिए मैंने फंक्शन को लूप के साथ लिखना समाप्त कर दिया। यह while -- साथ भी किया जा सकता है while --

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

जब आप जानते हैं कि आपने केवल एक मान के साथ एक सरणी को धक्का दिया है, तो अंतिम इंडेक्स का उपयोग करके शायद सबसे अच्छा समाधान रहता है, लेकिन यदि आपको बड़े सरणी के माध्यम से यात्रा करना है और परिणाम हर जगह हो सकता है, तो चीजों को तेज़ी से बनाने के लिए यह एक ठोस समाधान हो सकता है।

बिडरेक्शनल इंडेक्सऑफ / अंतिम इंडेक्सऑफ

function bidirectionalIndexOf(a, b, c, d, e){
  for(c=a.length,d=c*1; c--; ){
    if(a[c]==b) return c; //or this[c]===b
    if(a[e=d-1-c]==b) return e; //or a[e=d-1-c]===b
  }
  return -1
}

//Usage
bidirectionalIndexOf(array,'value');

प्रदर्शन का परीक्षण

http://jsperf.com/bidirectionalindexof

परीक्षण के रूप में मैंने 100k प्रविष्टियों के साथ एक सरणी बनाई।

तीन प्रश्न: शुरुआत में, बीच में और सरणी के अंत में।

मुझे आशा है कि आपको यह दिलचस्प भी मिलेगा और प्रदर्शन का परीक्षण होगा।

नोट: जैसा कि आप देख सकते हैं कि मैंने इंडेक्सऑफ और अंतिम index आउटपुट को प्रतिबिंबित करने के लिए फ़ंक्शन को थोड़ा संशोधित किया है (इसलिए मूल रूप से index साथ true और -1 साथ false )। इसे नुकसान नहीं पहुंचाया जाना चाहिए।

सरणी प्रोटोटाइप संस्करण

Object.defineProperty(Array.prototype,'bidirectionalIndexOf',{value:function(b,c,d,e){
  for(c=this.length,d=c*1; c--; ){
    if(this[c]==b) return c; //or this[c]===b
    if(this[e=d-1-c] == b) return e; //or this[e=d-1-c]===b
  }
  return -1
},writable:false, enumerable:false});

// Usage
array.bidirectionalIndexOf('value');

फ़ंक्शन को सही या गलत या ऑब्जेक्ट, स्ट्रिंग या जो भी हो, वापस करने के लिए आसानी से संशोधित किया जा सकता है।

और यहां while भिन्नता है:

function bidirectionalIndexOf(a, b, c, d){
  c=a.length; d=c-1;
  while(c--){
    if(b===a[c]) return c;
    if(b===a[d-c]) return d-c;
  }
  return c
}

// Usage
bidirectionalIndexOf(array,'value');

यह कैसे हो सकता है?

मुझे लगता है कि एक सरणी में परावर्तक सूचकांक प्राप्त करने के लिए सरल गणना इतनी सरल है कि वास्तविक लूप पुनरावृत्ति करने से यह दो गुना तेज है।

यहां एक जटिल उदाहरण है जो प्रति पुनरावृत्ति के तीन चेक कर रहा है, लेकिन यह केवल लंबी गणना के साथ संभव है जो कोड की मंदी का कारण बनता है।

http://jsperf.com/bidirectionalindexof/2


किसी भी तरह से सबसे अच्छा नहीं, लेकिन मैं सिर्फ रचनात्मक हो रहा था और प्रदर्शन के लिए जोड़ रहा था।

इसका इस्तेमाल न करें

Object.defineProperty(Array.prototype, 'exists', {
  value: function(element, index) {

    var index = index || 0

    return index === this.length ? -1 : this[index] === element ? index : this.exists(element, ++index)
  }
})


// Outputs 1
console.log(['one', 'two'].exists('two'));

// Outputs -1
console.log(['one', 'two'].exists('three'));

console.log(['one', 'two', 'three', 'four'].exists('four'));


ठीक है, आप परिणाम प्राप्त करने के लिए बस अपना कोड अनुकूलित कर सकते हैं ! ऐसा करने के कई तरीके हैं जो क्लीनर और बेहतर हैं, लेकिन मैं सिर्फ अपना पैटर्न प्राप्त करना चाहता हूं और उस पर लागू होता 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 contains(a, obj) {
    return a.some(function(element){return element == obj;})
}

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






browser