ลบองค์ประกอบอาร์เรย์ตามคุณสมบัติของวัตถุ


271

ฉันมีวัตถุหลายอย่างเช่น:

var myArray = [
    {field: 'id', operator: 'eq', value: id}, 
    {field: 'cStatus', operator: 'eq', value: cStatus}, 
    {field: 'money', operator: 'eq', value: money}
];

ฉันจะลบรายการเฉพาะตามคุณสมบัติได้อย่างไร

เช่นฉันจะลบวัตถุอาร์เรย์ที่มี 'เงิน' เป็นคุณสมบัติเขตข้อมูลได้อย่างไร

คำตอบ:


382

ความเป็นไปได้หนึ่งอย่าง:

myArray = myArray.filter(function( obj ) {
    return obj.field !== 'money';
});

โปรดทราบว่าfilterสร้างอาร์เรย์ใหม่ ตัวแปรอื่น ๆ ที่อ้างถึงอาร์เรย์เดิมจะไม่ได้รับข้อมูลที่กรองแม้ว่าคุณจะอัปเดตตัวแปรเดิมmyArrayด้วยการอ้างอิงใหม่ ใช้ด้วยความระมัดระวัง


6
โปรดทราบว่าfilter()จะใช้ได้เฉพาะกับ Internet Explorer 9+
jessegavin

@ jessegavin แน่นอน ฉันควรจะกล่าวว่ามีไลบรารีes5 shimที่ดีมากมายซึ่งเลียนแบบการทำงาน (ในกรณีที่คุณต้องการสนับสนุนเบราว์เซอร์รุ่นเก่า)
jAndy

3
filter()สร้างอาร์เรย์ใหม่ซึ่งใช้ได้ถ้าคุณสามารถกำหนดตัวแปรใหม่และรู้ว่าไม่มีส่วนอื่น ๆ ของรหัสที่อ้างอิงถึงมัน สิ่งนี้จะไม่ทำงานหากคุณต้องการแก้ไขวัตถุอาร์เรย์เดิมโดยเฉพาะ
Brian Glick

2
จะเกิดอะไรขึ้นถ้าอาเรย์นั้นเป็นโครงสร้างแบบต้นไม้ก่อน beforeDeleteOperationArray = [{"id": 3.1, "name": "test 3.1", "activityDetails": [{"id": 22, "name": "test 3.1"}, {"id": 23, "name": "เปลี่ยนแปลงการทดสอบ 23"}]}] และฉันต้องการที่จะลบ id: 23
ลืม

@forgottofly จุดดี - คำตอบใช้ได้เฉพาะในบางกรณีเท่านั้น คุณพบคำตอบสำหรับคำถามของคุณหรือไม่
JackTheKnife

88

วนซ้ำแถวลำดับและเรียงลำดับspliceที่คุณไม่ต้องการ สำหรับการใช้งานที่ง่ายขึ้นให้วนซ้ำไปข้างหลังดังนั้นคุณไม่ต้องคำนึงถึงลักษณะสดของอาเรย์:

for (var i = myArray.length - 1; i >= 0; --i) {
    if (myArray[i].field == "money") {
        myArray.splice(i,1);
    }
}

3
คุณหมายถึงอะไรโดยธรรมชาติของอาร์เรย์? @Neit the Dark
Absolut

29
@sisimh เขาหมายความว่าหากคุณวนซ้ำไปข้างหน้าอาร์เรย์โดยใช้ความยาวของมันเป็นส่วนหนึ่งของตรรกะการทำซ้ำและการเปลี่ยนแปลงความยาวของมันเพราะมันมีองค์ประกอบลบหรือเพิ่มคุณสามารถจบลงวิ่งออกจากจุดสิ้นสุดของอาร์เรย์หรือไม่ ทุกรายการในอาเรย์ การย้อนกลับทำให้มีโอกาสน้อยกว่ามากเมื่อทำงานกับดัชนีคงที่ 0 มากกว่าความยาวเคลื่อนที่
Klors

2
จะเกิดอะไรขึ้นถ้าอาเรย์นั้นเป็นโครงสร้างแบบต้นไม้ก่อน beforeDeleteOperationArray = [{"id": 3.1, "name": "test 3.1", "activityDetails": [{"id": 22, "name": "test 3.1"}, {"id": 23, "name": "เปลี่ยนแปลงการทดสอบ 23"}]}] และฉันต้องการที่จะลบ id: 23
ลืม

ค่อนข้างชัดเจน แต่ถ้าคุณคาดหวังว่าจะลบองค์ประกอบที่ไม่ซ้ำกันเพียงอย่างเดียวคุณสามารถแบ่งคำสั่ง 'if' สำหรับประสิทธิภาพการทำงานดังนั้นการวนซ้ำไม่จำเป็นต้องวนซ้ำในส่วนที่เหลือของอาร์เรย์
Patrick Borkowicz

@ Klors ขอบคุณที่อธิบาย มันดีไหมที่จะอ่านอาเรย์ย้อนหลังเหมือนคำตอบเสมอหรือไม่?
kittu

38

สมมติว่าคุณต้องการลบวัตถุที่สองโดยคุณสมบัติเขตข้อมูลนั้น

ด้วย ES6 มันง่ายเหมือนนี้

myArray.splice(myArray.findIndex(item => item.field === "cStatus"), 1)

7
ฉันลองแล้ว แต่แทนที่จะ "ลบ" รายการที่ 3 ออกจากอาร์เรย์ของรหัสของคุณ "กรอง" และแสดงรายการที่ 3 เท่านั้น
Compaq LE2202x

1
@ CompaqLE2202x 2 ปีต่อมาอาจเป็นที่ชัดเจนสำหรับคุณแล้ว แต่สำหรับนักพัฒนาในอนาคต: spliceเปลี่ยนอาร์เรย์เดิมดังนั้นค่าที่คุณได้รับกลับมาคือรายการที่ถูกลบ แต่ถ้าคุณดูmyArrayรายการต่อไปจะหายไป
David Mulder

16

คุณสามารถใช้ findIndex ของlodashเพื่อรับดัชนีขององค์ประกอบเฉพาะแล้วประกบกันโดยใช้

myArray.splice(_.findIndex(myArray, function(item) {
    return item.value === 'money';
}), 1);

ปรับปรุง

คุณสามารถใช้findIndexของ ES6 ()

เมธอด findIndex () ส่งคืนดัชนีขององค์ประกอบแรกในอาร์เรย์ที่เป็นไปตามฟังก์ชันการทดสอบที่ให้ไว้ มิฉะนั้นจะถูกส่งกลับ -1

myArray.splice(myArray.findIndex(myArray, function(item) {
    return item.value === 'money';
}), 1);

อาเรย์เป็นโครงสร้างต้นไม้คืออะไร?
ลืม

@forgottofly โครงสร้างต้นไม้? ฉันคิดว่าmyArrayที่นี่คือวัตถุมากมาย
Sridhar

3
จะทำอย่างไรถ้าอาร์เรย์เป็นโครงสร้างต้นไม้ var beforeDeleteOperationArray = [{"id": 3.1, "name": "test 3.1", "activityDetails": [{"id": 22, "name": "test 3.1"}, {"id": 23, "name": "เปลี่ยนแปลงการทดสอบ 23"}]}] และฉันต้องการลบ id: 23
ลืม

9

นี่เป็นอีกตัวเลือกการใช้ grep jQuery ส่งผ่านtrueเป็นพารามิเตอร์ตัวที่สามเพื่อให้แน่ใจว่า grep ลบรายการที่ตรงกับฟังก์ชันของคุณ

users = $.grep(users, function(el, idx) {return el.field == "money"}, true)

หากคุณใช้ jQuery Array.filterแล้วไม่มีชิมที่จำเป็นซึ่งเป็นอาจจะมีประโยชน์เมื่อเทียบกับการใช้



3

ต่อไปนี้เป็นรหัสถ้าคุณไม่ได้ใช้ jQuery การสาธิต

var myArray = [
    {field: 'id', operator: 'eq', value: 'id'}, 
    {field: 'cStatus', operator: 'eq', value: 'cStatus'}, 
    {field: 'money', operator: 'eq', value: 'money'}
];

alert(myArray.length);

for(var i=0 ; i<myArray.length; i++)
{
    if(myArray[i].value=='money')
        myArray.splice(i);
}

alert(myArray.length);

นอกจากนี้คุณยังสามารถใช้ไลบรารีขีดล่างซึ่งมีฟังก์ชันมากมาย

Underscoreเป็นไลบรารี่ของสายพานสำหรับจาวาสคริปต์ที่ให้การสนับสนุนการเขียนโปรแกรมการทำงานมากมาย


5
นี่เป็นตัวอย่างที่อันตรายมากที่จะทิ้งไว้บนเว็บ ... มันทำงานกับข้อมูลตัวอย่างได้ แต่ไม่ใช่กับสิ่งอื่นใด splice (i) หมายความว่ามันจะลบองค์ประกอบทั้งหมดในอาร์เรย์ที่เริ่มต้นที่และหลังจากอินสแตนซ์แรกที่ค่าคือเงินซึ่งลงไม่ตอบสนองความต้องการจาก op เลย หากเราเปลี่ยนเป็น splice (i, 1) มันจะยังคงไม่ถูกต้องเพราะมันจะไม่ประเมินรายการลำดับถัดไป (คุณจะต้องลดค่า i ด้วย) นี่คือเหตุผลที่คุณควรประมวลผลการดำเนินการลบในอาร์เรย์ย้อนกลับเพื่อลบ รายการจะไม่เปลี่ยนแปลงดัชนีของรายการถัดไปที่จะดำเนินการ
Chris Schaller

3
var myArray = [
    {field: 'id', operator: 'eq', value: id}, 
    {field: 'cStatus', operator: 'eq', value: cStatus}, 
    {field: 'money', operator: 'eq', value: money}
];
console.log(myArray.length); //3
myArray = $.grep(myArray, function(element, index){return element.field == "money"}, true);
console.log(myArray.length); //2

องค์ประกอบเป็นวัตถุในอาร์เรย์ พารามิเตอร์ที่ 3 trueหมายถึงจะส่งคืนอาร์เรย์ขององค์ประกอบที่ล้มเหลวในการทำงานตรรกะของคุณfalseหมายความว่าจะส่งกลับอาร์เรย์ขององค์ประกอบที่ล้มเหลวตรรกะการทำงานของคุณ


3

ใช้ห้องสมุดLodash :

var myArray = [
    {field: 'id', operator: 'eq', value: 'id'}, 
    {field: 'cStatus', operator: 'eq', value: 'cStatus'}, 
    {field: 'money', operator: 'eq', value: 'money'}
];
var newArray = _.remove(myArray, function(n) {
  return n.value === 'money';;
});
console.log('Array');
console.log(myArray);
console.log('New Array');
console.log(newArray);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>


2

ตามความคิดเห็นบางส่วนด้านบนด้านล่างเป็นรหัสวิธีการลบวัตถุตามชื่อคีย์และค่าคีย์

 var items = [ 
  { "id": 3.1, "name": "test 3.1"}, 
  { "id": 22, "name": "test 3.1" }, 
  { "id": 23, "name": "changed test 23" } 
  ]

    function removeByKey(array, params){
      array.some(function(item, index) {
        return (array[index][params.key] === params.value) ? !!(array.splice(index, 1)) : false;
      });
      return array;
    }

    var removed = removeByKey(items, {
      key: 'id',
      value: 23
    });

    console.log(removed);

1

วิธีแก้ปัญหาของ jAndy อาจดีที่สุด แต่ถ้าคุณไม่สามารถใช้ตัวกรองได้คุณสามารถทำสิ่งต่อไปนี้:

var myArray = [
    {field: 'id', operator: 'eq', value: 'id'}, 
    {field: 'cStatus', operator: 'eq', value: 'cStatus'}, 
    {field: 'money', operator: 'eq', value: "money"}
];

myArray.remove_key = function(key){
    var i = 0, 
        keyval = null;
    for( ; i < this.length; i++){
        if(this[i].field == key){
            keyval = this.splice(i, 1);
            break;
        }
    }
    return keyval;
}

1
เหตุใดฉันจึงไม่สามารถใช้ตัวกรอง () ได้
imperium2335

2
เพราะมันเป็นส่วนหนึ่งของ JavaScript 1.6 ซึ่งไม่รองรับโดย IE8 และเบราว์เซอร์ด้านล่างหรือรุ่นเก่ากว่า
Rob M.

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.