مصفوفه - كيف أقوم بإزالة عنصر معين من صفيف في JavaScript؟




مصفوفه ذات بعدين في الجافا (20)

لدي مجموعة من الأعداد الصحيحة ، وأنا أستخدم طريقة .push() لإضافة عناصر إليها.

هل هناك طريقة بسيطة لإزالة عنصر معين من صفيف؟ أي ما يعادل شيئًا مثل array.remove(int); .

لا بد لي من استخدام جافا سكريبت الأساسية - لا يسمح أطر العمل.

https://code.i-harness.com


ES6 وبدون طفرة: (أكتوبر 2016)

const removeByIndex = (list, index) =>
  [
    ...list.slice(0, index),
    ...list.slice(index + 1)
  ];

ثم :

removeByIndex([33,22,11,44],1) //=> [33,11,44]

تم تحريره في 2016 أكتوبر

  • افعل ذلك بطريقة بسيطة وبديهية وصريحة ( https://en.wikipedia.org/wiki/Occam%27s_razor )
  • هل هي غير قابلة للتغيير (تبقى المجموعة الأصلية دون تغيير)
  • افعل ذلك بوظائف JS القياسية ، إذا كان متصفحك لا يدعمها - استخدم polyfill

في هذا المثال ، استخدم وظيفة "array.filter (...)" لإزالة العناصر غير المرغوب فيها من المصفوفة ، وهذه الوظيفة لا تغير الصفيف الأصلي وتنشئ واحدة جديدة. إذا كان متصفحك لا يدعم هذه الوظيفة (على سبيل المثال ، IE قبل الإصدار 9 ، أو Firefox قبل الإصدار 1.5) ، فكر في استخدام مرشح الترشيح من Mozilla .

إزالة العنصر (ECMA-262 Edition 5 code aka oldstyle JS)

var value = 3

var arr = [1, 2, 3, 4, 5, 3]

arr = arr.filter(function(item) { 
    return item !== value
})

console.log(arr)
// [ 1, 2, 4, 5 ]

إزالة عنصر (كود ES2015)

let value = 3

let arr = [1, 2, 3, 4, 5, 3]

arr = arr.filter(item => item !== value)

console.log(arr)
// [ 1, 2, 4, 5 ]

IMPORTANT ES2015 "() => {}" صيغة الدالة arrow arrow غير مدعومة في IE على الإطلاق ، Chrome قبل إصدار 45 ، Firefox قبل الإصدار 22 ، Safari قبل الإصدار 10. لاستخدام صيغة ES2015 في المتصفحات القديمة ، يمكنك استخدام BabelJS

إزالة عناصر متعددة (رمز ES2016)

ميزة إضافية من هذه الطريقة هي أنه يمكنك إزالة عناصر متعددة

let forDeletion = [2, 3, 5]

let arr = [1, 2, 3, 4, 5, 3]

arr = arr.filter(item => !forDeletion.includes(item))
// !!! Read below about array.includes(...) support !!!

console.log(arr)
// [ 1, 4 ]

هام "array.includes (...)" وظيفة غير مدعومة في IE على الإطلاق ، Chrome قبل إصدار 47 ، و Firefox قبل الإصدار 43 ، و Safari قبل الإصدار 9 و Edge قبل الإصدار 14 ، لذلك ، هنا هو polyfill من Mozilla

إزالة عناصر متعددة (تجريبية JavaScript ES2018؟)

// array-lib.js

export function remove(...forDeletion) {
    return this.filter(item => !forDeletion.includes(item))
}

// main.js

import { remove } from './array-lib.js'

let arr = [1, 2, 3, 4, 5, 3]

// :: This-Binding Syntax Proposal
// using "remove" function as "virtual method"
// without extending Array.prototype
arr = arr::remove(2, 3, 5)

console.log(arr)
// [ 1, 4 ]

جربه بنفسك في BabelJS :)

مرجع


إذا كان لديك كائنات معقدة في الصفيف يمكنك استخدام المرشحات؟ في الحالات التي يكون فيها .inArray أو array.splice $ ليس سهل الاستخدام. خاصة إذا كانت الكائنات ضحلة في الصفيف.

على سبيل المثال ، إذا كان لديك كائن به حقل معرف وتريد إزالة الكائن من مصفوفة:

this.array = this.array.filter(function(element, i) {
    return element.id !== idToRemove;
});

إذا كنت تريد إزالة مصفوفة جديدة مع إزالة المواضع المحذوفة ، يمكنك دائمًا حذف العنصر المحدد وتصفية المصفوفة. قد يحتاج إلى امتداد لعنصر المصفوفة للمتصفحات التي لا تقوم بتطبيق طريقة التصفية ولكن على المدى الطويل أسهل لأن كل ما عليك فعله هو:

var my_array = [1,2,3,4,5,6];
delete my_array[4];
console.log(my_array.filter(function(a){return typeof a !== 'undefined';}));

يجب عرض [1, 2, 3, 4, 6]


تحقق من هذا الرمز. وهو يعمل في كل متصفح رئيسي .

remove_item = function (arr, value) {
    var b = '';
    for (b in arr) {
        if (arr[b] === value) {
            arr.splice(b, 1);
            break;
        }
    }
    return arr;
}

استدعاء هذه الوظيفة

remove_item(array,value);

في ما يلي بعض الطرق لإزالة عنصر من صفيف باستخدام جافا سكريبت .

لا تقوم كافة الطرق الموضحة بتحويل الصفيف الأصلي ، وبدلاً من ذلك قم بإنشاء صفيف جديد.

إذا كنت تعرف فهرس عنصر

افترض أن لديك صفيف ، وتريد إزالة عنصر في الموضع i .

تتمثل إحدى الطرق في استخدام slice() :

const items = ['a', 'b', 'c', 'd', 'e', 'f']
const i = 3
const filteredItems = items.slice(0, i-1).concat(items.slice(i, items.length))

console.log(filteredItems)

slice() بإنشاء صفيف جديد مع الفهارس التي يتلقاها. نقوم ببساطة بإنشاء مصفوفة جديدة ، بدءًا من البداية وحتى الفهرس الذي نريد إزالته ، وسَلسَلة صفيف آخر من الموضع الأول بعد الموضع الذي أزلناه إلى نهاية المصفوفة.

إذا كنت تعرف القيمة

في هذه الحالة ، يكون أحد الخيارات الجيدة هو استخدام filter() ، والذي يقدم أسلوبًا أكثر إعلانًا :

const items = ['a', 'b', 'c', 'd', 'e', 'f']
const valueToRemove = 'c'
const filteredItems = items.filter(item => item !== valueToRemove)

console.log(filteredItems)

هذا يستخدم وظائف السهم ES6. يمكنك استخدام الوظائف التقليدية لدعم المتصفحات القديمة:

const items = ['a', 'b', 'c', 'd', 'e', 'f']
const valueToRemove = 'c'
const filteredItems = items.filter(function(item) {
  return item !== valueToRemove
})

console.log(filteredItems)

أو يمكنك استخدام بابل وترجم شفرة ES6 مرة أخرى إلى ES5 لجعلها أكثر قابلية للهضم إلى المتصفحات القديمة ، مع كتابة JavaScript الحديثة في شفرتك.

إزالة عناصر متعددة

ماذا لو بدلاً من عنصر واحد ، تريد إزالة العديد من العناصر؟

دعونا نجد أبسط حل.

حسب الفهرس

يمكنك فقط إنشاء وظيفة وإزالة العناصر في سلسلة:

const items = ['a', 'b', 'c', 'd', 'e', 'f']

const removeItem = (items, i) =>
  items.slice(0, i-1).concat(items.slice(i, items.length))

let filteredItems = removeItem(items, 3)
filteredItems = removeItem(filteredItems, 5)
//["a", "b", "c", "d"]

console.log(filteredItems)

بالقيمة

يمكنك البحث عن التضمين داخل وظيفة معاودة الاتصال:

const items = ['a', 'b', 'c', 'd', 'e', 'f']
const valuesToRemove = ['c', 'd']
const filteredItems = items.filter(item => !valuesToRemove.includes(item))
// ["a", "b", "e", "f"]

console.log(filteredItems)

تجنب تحور الصفيف الأصلي

splice()(لا ينبغي الخلط مع slice()) يتغير المصفوفة الأصلية ، ويجب تجنبها.

(تم نشره أصلاً على https://flaviocopes.com/how-to-remove-item-from-array/ )


كان صديق يواجه مشاكل في Internet Explorer 8 ، وأظهر لي ما فعله. قلت له أنه كان خطأ ، وقال لي أنه حصل على الجواب هنا. لن تعمل الإجابة الأعلى الحالية في جميع المتصفحات (Internet Explorer 8 على سبيل المثال) ، وستقوم فقط بإزالة التواجد الأول للعنصر.

قم بإزالة كافة المثيلات من صفيف

function remove(arr, item) {
    for (var i = arr.length; i--;) {
        if (arr[i] === item) {
            arr.splice(i, 1);
        }
    }
}

يتدفق عبر الصفيف للخلف (بما أن الفهارس والطول سيتغيران عند إزالة العناصر) ويزيل العنصر إذا تم العثور عليه. يعمل في جميع المتصفحات.


لا أعرف كيف تتوقع أن تتصرف array.remove(int) . هناك ثلاثة احتمالات يمكن أن أفكر في أنك قد ترغب.

لإزالة عنصر مصفوفة في فهرس i :

array.splice(i, 1);

إذا كنت تريد إزالة كل عنصر مع number القيمة من المصفوفة:

for(var i = array.length - 1; i >= 0; i--) {
    if(array[i] === number) {
       array.splice(i, 1);
    }
}

إذا كنت ترغب فقط في جعل العنصر الموجود في الفهرس i لم يعد موجودًا ، ولكنك لا تريد أن تتغير مؤشرات العناصر الأخرى:

delete array[i];

هناك طريقتان رئيسيتان:

  1. splice () : anArray.splice(index, 1);

  2. delete : delete anArray[index];

كن حذرا عند استخدام حذف لصفيف. من الجيد حذف سمات الكائنات ولكن ليس جيدًا للصفائف. من الأفضل استخدام splice للصفائف.

ضع في اعتبارك أنه عند استخدام delete لصفيف ، يمكنك الحصول على نتائج خاطئة لـ anArray.length . بمعنى آخر ، سيؤدي delete إلى إزالة العنصر ولكن لن يؤدي إلى تحديث قيمة قيمة الطول.

يمكنك أيضًا توقع وجود ثغرات في أرقام الفهرس بعد استخدام الحذف ، على سبيل المثال ، قد ينتهي بك الأمر مع وجود الفهارس 1،3،4،8،9،11 والطول كما كان قبل استخدام الحذف. في هذه الحالة ، سوف تتعطل جميع المفهرسة للحلقات ، لأن الفهارس لم تعد متسلسلة.

إذا تم إجبارك على استخدام delete لسبب ما ، فيجب عليك استخدام for each حلقة عندما تحتاج إلى إجراء التكرار خلال المصفوفات. كما واقع الأمر ، دائما تجنب استخدام مفهرسة للحصول على الحلقات ، إذا كان ذلك ممكنا. بهذه الطريقة سيكون الرمز أكثر قوة وأقل عرضة للمشاكل مع الفهارس.


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

var myArray = [1,2,3,4,5,6];

لنفترض أنك تريد إزالة 5 من المصفوفة ، يمكنك القيام بذلك ببساطة.

myArray = myArray.filter(value => value !== 5);

سيعطيك هذا صفيفًا جديدًا بدون القيمة التي تريد إزالتها. لذلك ستكون النتيجة

 [1,2,3,4,6]; // 5 has been removed from this array

لمزيد من الفهم ، يمكنك قراءة وثائق MDN على Array.filter filter


يمكن استخدام Underscore.js لحل المشكلات مع متصفحات متعددة. ويستخدم أساليب متصفح البناء في حالة وجودها. إذا كانوا غائبين مثل في حالة إصدارات Internet Explorer القديمة ، فإنه يستخدم أساليب مخصصة خاصة به.

مثال بسيط لإزالة العناصر من الصفيف (من موقع الويب):

_.without([1, 2, 1, 0, 3, 1, 4], 0, 1); // => [2, 3, 4]

يمكنك استخدام ES6.

var array=['1','2','3','4','5','6']
var index = array.filter((value)=>value!='3');

انتاج :

["1", "2", "4", "5", "6"]

يمكنك القيام بذلك بسهولة باستخدام طريقة filter :

function remove(arrOriginal, elementToRemove){
    return arrOriginal.filter(function(el){return el !== elementToRemove});
}
console.log( remove([1, 2, 1, 0, 3, 1, 4], 1) );

هذا يزيل جميع العناصر من المصفوفة ويعمل أيضا أسرع ثم مزيج من شريحة و indexOf


نشر John Resig تطبيقًا جيدًا :

// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function(from, to) {
  var rest = this.slice((to || from) + 1 || this.length);
  this.length = from < 0 ? this.length + from : from;
  return this.push.apply(this, rest);
};

إذا كنت لا ترغب في توسيع نطاق كائن عام ، فيمكنك القيام بشيء مثل ما يلي ، بدلاً من ذلك:

// Array Remove - By John Resig (MIT Licensed)
Array.remove = function(array, from, to) {
    var rest = array.slice((to || from) + 1 || array.length);
    array.length = from < 0 ? array.length + from : from;
    return array.push.apply(array, rest);
};

ولكن السبب الرئيسي في نشر هذا هو تحذير المستخدمين من التطبيق البديل المقترح في التعليقات على تلك الصفحة (14 ديسمبر 2007):

Array.prototype.remove = function(from, to){
  this.splice(from, (to=[0,from||1,++to-from][arguments.length])<0?this.length+to:to);
  return this.length;
};

يبدو أنها تعمل بشكل جيد في البداية ، ولكن من خلال عملية مؤلمة اكتشفت أنه فشل عند محاولة إزالة العنصر الثاني إلى آخر في صفيف. على سبيل المثال ، إذا كان لديك صفيف مكون من 10 عناصر وحاولت إزالة العنصر 9 باستخدام هذا:

myArray.remove(8);

ينتهي بك الأمر مع صفيف 8 عنصر. لا أعرف السبب ، لكنني أكدت أن تطبيق John الأصلي لا يتضمن هذه المشكلة.


حسنًا ، على سبيل المثال ، تواجه الصفيف أدناه:

var num = [1, 2, 3, 4, 5];

ونريد حذف الرقم 4 ، يمكنك ببساطة عمل الكود التالي:

num.splice(num.indexOf(4), 1); //num will be [1, 2, 3, 5];

إذا قمت بإعادة استخدام هذه الوظيفة ، فأنت تكتب دالة قابلة لإعادة الاستخدام والتي سيتم إرفاقها بوظيفة الصفيف المحلي مثل أدناه:

Array.prototype.remove = Array.prototype.remove || function(x) {
  const i = this.indexOf(x);
  if(i===-1) return;
  this.splice(i, 1); //num.remove(5) === [1, 2, 3];
}

ولكن ماذا لو كنت تواجه المجموعة أدناه بدلاً من ذلك بقليل من [5] s في المصفوفة؟

var num = [5, 6, 5, 4, 5, 1, 5];

نحتاج إلى حلقة للتحقق منها جميعًا ، ولكن الطريقة الأسهل والأكثر فاعلية هي استخدام وظائف جافا سكريبت المضمنة ، لذلك نكتب دالة تستخدم فلترًا مثل:

const _removeValue = (arr, x) => arr.filter(n => n!==x);
//_removeValue([1, 2, 3, 4, 5, 5, 6, 5], 5) //return [1, 2, 3, 4, 6]

هناك أيضًا مكتبات تابعة لأطراف ثالثة تساعدك في القيام بذلك ، مثل Lodash أو Underscore ، للحصول على مزيد من المعلومات ، انظر إلى lodash _.pull أو _.pullAt أو _.without.


استنادًا إلى جميع الإجابات التي كانت صحيحة بشكل أساسي ومراعاة أفضل الممارسات المقترحة (لا سيما استخدام Array.prototype مباشرةً) ، توصلت إلى الشفرة التالية:

function arrayWithout(arr, values) {
  var isArray = function(canBeArray) {
    if (Array.isArray) {
      return Array.isArray(canBeArray);
    }
    return Object.prototype.toString.call(canBeArray) === '[object Array]';
  };

  var excludedValues = (isArray(values)) ? values : [].slice.call(arguments, 1);
  var arrCopy = arr.slice(0);

  for (var i = arrCopy.length - 1; i >= 0; i--) {
    if (excludedValues.indexOf(arrCopy[i]) > -1) {
      arrCopy.splice(i, 1);
    }
  }

  return arrCopy;
}

مراجعة الوظيفة المذكورة أعلاه ، على الرغم من حقيقة أنه يعمل بشكل جيد ، أدركت أنه يمكن أن يكون هناك بعض التحسن في الأداء. أيضا استخدام ES6 بدلا من ES5 هو نهج أفضل بكثير. تحقيقا لهذه الغاية ، هذه هي الكود المحسن:

const arrayWithoutFastest = (() => {
  const isArray = canBeArray => ('isArray' in Array) 
    ? Array.isArray(canBeArray) 
    : Object.prototype.toString.call(canBeArray) === '[object Array]';

  let mapIncludes = (map, key) => map.has(key);
  let objectIncludes = (obj, key) => key in obj;
  let includes;

  function arrayWithoutFastest(arr, ...thisArgs) {
    let withoutValues = isArray(thisArgs[0]) ? thisArgs[0] : thisArgs;

    if (typeof Map !== 'undefined') {
      withoutValues = withoutValues.reduce((map, value) => map.set(value, value), new Map());
      includes = mapIncludes;
    } else {
      withoutValues = withoutValues.reduce((map, value) => { map[value] = value; return map; } , {}); 
      includes = objectIncludes;
    }

    const arrCopy = [];
    const length = arr.length;

    for (let i = 0; i < length; i++) {
      // If value is not in exclude list
      if (!includes(withoutValues, arr[i])) {
        arrCopy.push(arr[i]);
      }
    }

    return arrCopy;
  }

  return arrayWithoutFastest;  
})();

كيف تستعمل:

const arr = [1,2,3,4,5,"name", false];

arrayWithoutFastest(arr, 1); // will return array [2,3,4,5,"name", false]
arrayWithoutFastest(arr, 'name'); // will return [2,3,4,5, false]
arrayWithoutFastest(arr, false); // will return [2,3,4,5]
arrayWithoutFastest(arr,[1,2]); // will return [3,4,5,"name", false];
arrayWithoutFastest(arr, {bar: "foo"}); // will return the same array (new copy)

أقوم حاليًا بكتابة مشاركة مدونة قمت فيها بمقارنة عدة حلول لـ Array بدون مشكلة وقارنت الوقت المستغرق لتشغيله. سأقوم بتحديث هذه الإجابة بالرابط بمجرد أن أنتهي من هذه المشاركة. فقط لإعلامك ، لقد قارنت ما سبق من دون lodash وفي حالة دعم المستعرض Map، فإنه يدق lodash! لاحظ أني لا أستخدم Array.prototype.indexOfأو Array.prototype.includesألصق exlcudeValues ​​في Mapأو Objectيجعل الاستعلام أسرع! ( https://jsperf.com/array-without-benchmark-against-lodash )


لديك مجموعة من 1 إلى 9 وتريد إزالة 5 استخدام أدناه رمز.

var numberArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];

var newNumberArray = numberArray.filter(m => {
  return m !== 5;
});

console.log("new Array, 5 removed", newNumberArray);

إذا كنت ترغب في قيمة متعددة السابقين: - 1،7،8

var numberArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];

var newNumberArray = numberArray.filter(m => {
  return (m !== 1) && (m !== 7) && (m !== 8);
});

console.log("new Array, 5 removed", newNumberArray);

إذا كنت ترغب في إزالة قيمة المصفوفة في الصفيف السابق: - [3،4،5]

var numberArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var removebleArray = [3,4,5];

var newNumberArray = numberArray.filter(m => {
    return !removebleArray.includes(m);
});

console.log("new Array, [3,4,5] removed", newNumberArray);

يتضمن متصفح معتمد هو link


يمكنك إجراء حلقة للخلف للتأكد من عدم فك مؤشر الفهارس ، إذا كانت هناك مثيلات متعددة للعنصر.

var myElement = "chocolate";
var myArray = ['chocolate', 'poptart', 'poptart', 'poptart', 'chocolate', 'poptart', 'poptart', 'chocolate'];

/* Important code */
for (var i = myArray.length - 1; i >= 0; i--) {
    if (myArray[i] == myElement) myArray.splice(i, 1);
}

عرض حي


أعلم أن هناك الكثير من الإجابات بالفعل ، ولكن يبدو أن الكثير منها يزيد من تعقيد المشكلة. هنا طريقة بسيطة ، متكررة لإزالة جميع حالات المفتاح - مكالمات ذاتية حتى يتم العثور على الفهرس. نعم ، إنها تعمل فقط في المتصفحات indexOf، ولكنها بسيطة ويمكن أن تكون معبأة بسهولة.

وظيفة قائمة بذاتها

function removeAll(array, key){
    var index = array.indexOf(key);

    if(index === -1) return;

    array.splice(index, 1);
    removeAll(array,key);
}

طريقة النموذج الأولي

Array.prototype.removeAll = function(key){
    var index = this.indexOf(key);

    if(index === -1) return;

    this.splice(index, 1);
    this.removeAll(key);
}

  Array.prototype.removeItem = function(a) {
            for (i = 0; i < this.length; i++) {
                if (this[i] == a) {
                    for (i2 = i; i2 < this.length - 1; i2++) {
                        this[i2] = this[i2 + 1];
                    }
                    this.length = this.length - 1
                    return;
                }
            }
        }

    var recentMovies = ['Iron Man', 'Batman', 'Superman', 'Spiderman'];
    recentMovies.removeItem('Superman');




arrays