remove - كيف أتحقق مما إذا كان الصفيف يحتوي على كائن في JavaScript؟




remove element from array javascript (20)

ECMAScript 6 لديه اقتراح أنيق على العثور عليها.

تقوم طريقة البحث بتنفيذ وظيفة معاودة الاتصال مرة واحدة لكل عنصر موجود في المصفوفة حتى تعثر على وظيفة حيث تقوم معاودة الاتصال بإرجاع قيمة حقيقية. إذا تم العثور على هذا العنصر ، فابحث على الفور عن قيمة هذا العنصر. خلاف ذلك ، والعثور على إرجاع غير محدد. يتم استدعاء رد الاتصال فقط من أجل فهارس الصفيف التي لها قيم معينة؛ لا يتم استدعاء الفهارس التي تم حذفها أو التي لم يتم تعيين قيم لها.

هنا هو وثائق MDN على ذلك.

تعمل وظيفة البحث على هذا النحو.

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

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

هل هناك طريقة أفضل وأكثر إيجازًا لتحقيق ذلك؟

هذا يرتبط ارتباطًا وثيقًا بمسألة Stack Overflow أفضل طريقة للعثور على عنصر في مصفوفة JavaScript؟ الذي يعالج الكائنات في صفيف باستخدام indexOf .


أنا استخدم ما يلي:

Array.prototype.contains = function (v) {
    return this.indexOf(v) > -1;
}

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

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

إذا كنت تستخدم JavaScript 1.6 أو أحدث (Firefox 1.5 أو أحدث) ، يمكنك استخدام 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;
      };
}

إن توسيع كائن Array جافا سكريبت هو فكرة سيئة للغاية لأنك تقدم خصائص جديدة (طرقك المخصصة) for-in الحلقات التي يمكن أن تحطم البرامج النصية الموجودة. قبل بضع سنوات ، كان على مؤلفي مكتبة Prototype أن يعيدوا تصميم تطبيق المكتبة لإزالة هذا النوع من الأشياء.

إذا كنت لا داعي للقلق بشأن التوافق مع جافا سكريبت الأخرى التي تعمل على صفحتك ، فابحث عنها ، وإلا ، فأنا أوصي بحل وظيفي أكثر حرًا ، ولكن أكثر أمانًا.


استخدام لواضع some الوظائف.

إنه موجز ودقيق ولديه دعم كبير عبر النظام الأساسي.

الإجابة المقبولة لا تفي بالمتطلبات.

المتطلبات: التوصية بأكثر الطرق اختصارًا وفعالية لمعرفة ما إذا كانت مصفوفة جافا سكريبت تحتوي على كائن.

الجواب المقبول:

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

توصيتي:

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

ملاحظات:

$ .inArray يعمل بشكل جيد لتحديد ما إذا كانت القيمة العددية موجودة في مصفوفة من scalars ...

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

... ولكن السؤال يسأل بوضوح عن طريقة فعالة لتحديد ما إذا كان كائن موجود في مصفوفة.

من أجل التعامل مع كلا العددين والكائنات ، يمكنك القيام بذلك:

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

استعمال:

function isInArray(array, search)
{
    return array.indexOf(search) >= 0;
}

// Usage
if(isInArray(my_array, "my_value"))
{
    //...
}


الخطوط الملاحية المنتظمة واحد:

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


تفترض الإجابات الأعلى أنواعًا بدائية ، ولكن إذا كنت تريد معرفة ما إذا كان الصفيف يحتوي على كائن به سمة ما ، فإن 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 لأنها ترجع قيمة منطقية:

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

* كما أشار jamess في التعليق ، اعتبارا من اليوم ، سبتمبر 2018 ، Array.prototype.some() مدعوم بالكامل: جدول دعم caniuse.com


في حين أن array.indexOf(x)!=-1 هي الطريقة الأكثر اختصارًا للقيام بذلك (وقد تم دعمها من قبل المستعرضات التي لا تستخدم Internet Explorer لأكثر من عشر سنوات ...) ، فهي ليست O (1) ، بل O ( ن) ، وهو أمر فظيع. إذا لم يتم تغيير الصفيف الخاص بك ، يمكنك تحويل الصفيف الخاص بك إلى hashtable ، ثم قم بعمل 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 إلى "تجميد" صفيف وتخزين ملف قابل للتخزين في this._cache في سطرين ، سيعطي هذا نتائج خاطئة إذا اخترت تحرير الصفيف الخاص بك في وقت لاحق. لا تحتوي JavaScript على خطافات كافية تمكنك من الحفاظ على هذه الحالة ، على عكس بايثون على سبيل المثال.)


نستخدم هذا المقتطف (يعمل مع الكائنات ، المصفوفات ، السلاسل):

/*
 * @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

يقدم ECMAScript 7 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

على عكس indexOf ، والذي يستخدم SameValueZero صارمة للمساواة ، includes مقارنات باستخدام خوارزمية SameValueZero المساواة. وهذا يعني أنه بإمكانك اكتشاف ما إذا كانت مصفوفة تحتوي على NaN :

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

أيضًا بخلاف indexOf ، لا includes تخطي المؤشرات المفقودة:

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

لا يزال حاليًا مسودة ، ولكن يمكن polyfill لجعلها تعمل على جميع المتصفحات.


يمكنك أيضًا استخدام هذه الحيلة:

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

b هي القيمة ، a المصفوفة. تقوم بإرجاع true أو false :

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

التحديث: كما يذكرorip في التعليقات ، تم إجراء الاختبار القياسي المرتبط في عام 2008 ، لذا قد لا تكون النتائج ذات صلة بالمتصفحات الحديثة. ومع ذلك ، ربما تحتاج إلى هذا لدعم المتصفحات غير الحديثة على أي حال وربما لم يتم تحديثها منذ ذلك الحين. اختبر دائما لنفسك.

كما قال الآخرون ، فإن التكرار عبر المصفوفة هو على الأرجح أفضل طريقة ، ولكن ثبت أن التراجع while التكرار هو أسرع طريقة للتكرار في JavaScript. لذلك قد تحتاج إلى إعادة كتابة التعليمات البرمجية كما يلي:

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

بأي حال من الأحوال أفضل ، ولكن كنت مجرد الحصول على الإبداع وإضافة إلى ذخيرة.

لا تستخدم هذا

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


كما ذكر آخرون ، يمكنك استخدامه Array.indexOf، ولكنه غير متوفر في جميع المتصفحات. إليك الشفرة من https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf لجعلها تعمل بنفس الطريقة في المتصفحات القديمة.

يعد indexOf إضافة حديثة إلى معيار ECMA-262 ؛ على هذا النحو قد لا تكون موجودة في جميع المتصفحات. يمكنك حل هذه المشكلة من خلال إدراج الشفرة التالية في بداية نصوصك البرمجية ، مما يسمح باستخدام indexOf في التطبيقات التي لا تدعمها أصلاً. هذه الخوارزمية هي بالضبط تلك المحددة في ECMA-262 ، الطبعة الخامسة ، بافتراض أن قيمة Object ID و TypeError و Number و 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;
    }
}





browser