javascript ค้นหาและลบวัตถุในอาร์เรย์ตามค่าคีย์


145

ฉันลองใช้หลายวิธีในการค้นหาวัตถุในอาร์เรย์โดยที่ ID = var และหากพบให้ลบวัตถุออกจากอาร์เรย์และส่งคืนอาร์เรย์ของวัตถุใหม่

ข้อมูล:

[
    {"id":"88","name":"Lets go testing"},
    {"id":"99","name":"Have fun boys and girls"},
    {"id":"108","name":"You are awesome!"}
]

ฉันสามารถค้นหาอาร์เรย์โดยใช้ jQuery $ grep;

var id = 88;

var result = $.grep(data, function(e){ 
     return e.id == id; 
});

แต่ฉันจะลบวัตถุทั้งหมดได้อย่างไรเมื่อ id == 88 และส่งคืนข้อมูลเช่นนี้:

ข้อมูล:

[
    {"id":"99","name":"Have fun boys and girls"},
    {"id":"108","name":"You are awesome!"}
]

แล้วการใช้sliceฟังก์ชันและforลูปเล็ก ๆล่ะ?
Ahmed Hamdy

1
แน่นอน แต่เหตุผลที่ฉันเขียนคำถามนี้เป็นเพราะฉันติดขัด;) ตัวอย่างใด ๆ ?
ทอม

ตรวจสอบโพสต์นี้stackoverflow.com/questions/10827894/…
Ahmed Hamdy

ชื่อเรื่องและข้อความคำถามดูเหมือนจะขัดแย้งกัน ... แนะนำสองแนวทางที่แตกต่างกันอย่างสิ้นเชิง: A.ลบรายการออกจากอาร์เรย์เทียบกับ B.สร้างอาร์เรย์ใหม่ที่กรองแล้ว
ศีล

คำตอบ:


157

ฉันสามารถ grep อาร์เรย์สำหรับ id แต่ฉันจะลบอ็อบเจ็กต์ทั้งหมดโดยที่ id == 88 ได้อย่างไร

เพียงกรองตามเพรดิเคตตรงข้าม:

var data = $.grep(data, function(e){ 
     return e.id != id; 
});

13
คำตอบนี้เป็นวิธีแก้ปัญหาที่กระชับและเป็นสำนวนที่สุดสำหรับ jQuery
Bryan

1
ในกรณีที่คุณต้องการลบรายการทั้งหมดด้วย id = บางอย่างก็ใช้ได้ ... แต่ระวังเมื่อใช้ $ .grep เนื่องจากค้นหาอาร์เรย์เต็มรูปแบบและอาร์เรย์แบบยาวจะไม่มีประสิทธิภาพ บางครั้งคุณต้องตรวจสอบว่ามีองค์ประกอบอยู่ในอาร์เรย์ด้วย ID ที่กำหนดหรือไม่จากนั้นจะดีกว่าถ้าใช้วิธีการวนซ้ำแบบอื่น)
julianox

1
สิ่งนี้ไม่ได้ลบวัตถุนั้นออกจากรายการ
อรุณศรีวรรณ

1
@ArunSivan sliceไม่ได้ลบอะไรเลย ไม่แน่ใจว่าคุณกำลังทำอะไรอยู่ ถ้าคุณมีปัญหาที่เฉพาะเจาะจงตัวคุณเองคุณอาจต้องการที่จะถามคำถามใหม่
Bergi

1
@Learnerdata.filter(e => !ids.includes(e.id))
Bergi

166

นี่คือวิธีแก้ปัญหาหากคุณไม่ได้ใช้ jquery:

myArray = myArray.filter(function( obj ) {
  return obj.id !== id;
});

2
นี้จะดีกว่าทำfindIndex()แล้วsplice(index, 1)ในอาร์เรย์พ่อแม่?
Alex

splice กลายพันธุ์อาร์เรย์ต้นทาง ด้วยตัวกรองคุณมีทางเลือก
velop

14
คุณสามารถลดเป็นบรรทัดเดียวได้โดยใช้: myArr = myArray.filter (obj => obj.id! == id);
DBrown

3
กระชับมากยิ่งขึ้นarr = arr.filter( obj => obj.id !== id);
โอมาร์

87

คุณสามารถทำให้สิ่งนี้ง่ายขึ้นและไม่จำเป็นต้องใช้ jquery ที่นี่

var id = 88;

for(var i = 0; i < data.length; i++) {
    if(data[i].id == id) {
        data.splice(i, 1);
        break;
    }
}

เพียงแค่วนซ้ำตามรายการค้นหารหัสที่ตรงกันประกบแล้วแตกเพื่อออกจากลูปของคุณ


17
+1 แต่คุณควรระบุว่าสิ่งนี้จะลบเฉพาะรายการแรกที่ตรงกัน
Bergi

6
... และถ้าคุณต้องการที่จะลบแต่ละรายการที่ตรงกับห่วงในการสั่งซื้อกลับด้วยและไม่ได้ใช้i=data.length; i > 0; i-- break
Jeremy Belolo

3
i = data.lengthจะแตกdata[i]มันควรจะเป็นแบบไหนi=data.length -1 ; i > -1; i--
distante

35

มีวิธีใหม่ในการทำเช่นนี้ใน ES6 / 2015 โดยใช้ findIndex และตัวดำเนินการกระจายอาร์เรย์:

const index = data.findIndex(obj => obj.id === id);
const newData = [
    ...data.slice(0, index),
    ...data.slice(index + 1)
]

คุณสามารถเปลี่ยนเป็นฟังก์ชันเพื่อนำกลับมาใช้ใหม่ในภายหลังได้ดังนี้:

function remove(array, key, value) {
    const index = array.findIndex(obj => obj[key] === value);
    return index >= 0 ? [
        ...array.slice(0, index),
        ...array.slice(index + 1)
    ] : array;
}

ด้วยวิธีนี้คุณสามารถลบรายการด้วยคีย์ที่แตกต่างกันโดยใช้วิธีการเดียว (และหากไม่มีวัตถุที่ตรงตามเกณฑ์คุณจะได้รับอาร์เรย์เดิมคืน):

const newData = remove(data, "id", "88");
const newData2 = remove(data, "name", "You are awesome!");

หรือคุณสามารถวางไว้ใน Array.prototype ของคุณ:

Array.prototype.remove = function (key, value) {
    const index = this.findIndex(obj => obj[key] === value);
    return index >= 0 ? [
        ...this.slice(0, index),
        ...this.slice(index + 1)
    ] : this;
};

และใช้วิธีนี้:

const newData = data.remove("id", "88");
const newData2 = data.remove("name", "You are awesome!");

findIndex () เยี่ยมมาก! 👍
danielcraigie

จะเกิดอะไรขึ้นถ้าคุณมีคีย์และค่ามากกว่าหนึ่ง
QMaster

9

สมมติว่ารหัสไม่ซ้ำกันและคุณจะต้องลบองค์ประกอบเดียวเท่านั้นspliceควรทำเคล็ดลับ:

var data = [
  {"id":"88","name":"Lets go testing"},
  {"id":"99","name":"Have fun boys and girls"},
  {"id":"108","name":"You are awesome!"}
],
id = 88;

console.table(data);

$.each(data, function(i, el){
  if (this.id == id){
    data.splice(i, 1);
  }
});

console.table(data);

คุณมีองค์ประกอบในฟังก์ชันเรียกกลับของคุณย้อนกลับ each(data,function(idx,ele)มันควรจะเป็น ฉันจะเรียกเก็บเงินคุณในภายหลังเป็นเวลา 30 นาทีที่ฉันเสียไปเพื่อหาสิ่งนั้น :)
CSharper

อ๊ะ. อย่างน้อยที่สุดที่ฉันสามารถทำได้ในกรณีนั้นคืออัปเดตคำตอบของฉัน ฉันรู้สึกแย่มากกับชีวิตที่เสียไป 30 นาทีของคุณ
James Hibbard

5
var items = [
  {"id":"88","name":"Lets go testing"},
  {"id":"99","name":"Have fun boys and girls"},
  {"id":"108","name":"You are awesome!"}
];

หากคุณใช้ jQuery ให้ใช้jQuery.grepดังนี้:

items = $.grep(items, function(item) { 
  return item.id !== '88';
});
// items => [{ id: "99" }, { id: "108" }]

ใช้ ES5 Array.prototype.filter :

items = items.filter(function(item) { 
  return item.id !== '88'; 
});
// items => [{ id: "99" }, { id: "108" }]

1
โน๊ะ! อย่าใช้jQueryแผนที่เป็นตัวกรอง
Bergi

1
ตกลง! โซลูชันของคุณด้วย grep เป็นโซลูชันที่เหมาะสมกับ jQuery
nekman

4

บางทีคุณอาจกำลังมองหา$.grep()ฟังก์ชัน:

arr = [
  {"id":"88","name":"Lets go testing"},
  {"id":"99","name":"Have fun boys and girls"},
  {"id":"108","name":"You are awesome!"}
];

id = 88;
arr = $.grep(arr, function(data, index) {
   return data.id != id
});

3

siftเป็นตัวกรองคอลเลกชันที่มีประสิทธิภาพสำหรับการดำเนินการเช่นนี้และตัวกรองขั้นสูงอื่น ๆ อีกมากมาย ทำงานฝั่งไคลเอ็นต์ในเบราว์เซอร์หรือฝั่งเซิร์ฟเวอร์ใน node.js

var collection = [
    {"id":"88","name":"Lets go testing"},
    {"id":"99","name":"Have fun boys and girls"},
    {"id":"108","name":"You are awesome!"}
];
var sifted = sift({id: {$not: 88}}, collection);

มันสนับสนุนฟิลเตอร์เช่น$in, $nin, $exists, $gte, $gt, $lte, $lt, $eq, $ne, $mod, $all, $and, $or, $nor, $not, $size, $typeและ$regexและมุ่งมั่นที่จะใช้ API เข้ากันได้กับ MongoDB กรองคอลเลกชัน


ทำไมไม่มี upwotes? หากสิ่งนี้ได้รับการเขียนอย่างถูกต้องและไม่มีจุดบกพร่องที่น่ากลัวสิ่งนี้ควรเป็นประโยชน์อย่างยิ่ง
Max Yari

2
Array.prototype.removeAt = function(id) {
    for (var item in this) {
        if (this[item].id == id) {
            this.splice(item, 1);
            return true;
        }
    }
    return false;
}

นี่ควรทำเคล็ดลับjsfiddle


0

ตรวจสอบให้แน่ใจว่าคุณบังคับรหัสอ็อบเจ็กต์เป็นจำนวนเต็มหากคุณทดสอบความเท่าเทียมกันอย่างเข้มงวด:

var result = $.grep(data, function(e, i) { 
  return +e.id !== id;
});

การสาธิต


0

หากคุณใช้ขีดล่าง js การลบออบเจ็กต์ตามคีย์นั้นทำได้ง่าย http://underscorejs.org ตัวอย่าง:

  var temp1=[{id:1,name:"safeer"},  //temp array
             {id:2,name:"jon"},
             {id:3,name:"James"},
             {id:4,name:"deepak"},
             {id:5,name:"ajmal"}];

  var id = _.pluck(temp1,'id'); //get id array from temp1
  var ids=[2,5,10];             //ids to be removed
  var bool_ids=[];
  _.each(ids,function(val){
     bool_ids[val]=true;
  });
  _.filter(temp1,function(val){
     return !bool_ids[val.id];
  });

0

เห็นด้วยกับคำตอบวิธีง่ายๆหากคุณต้องการค้นหาและคัดค้านโดย id และลบออกเป็นเหมือนโค้ดด้านล่าง

   var obj = JSON.parse(data);
   var newObj = obj.filter(item=>item.Id!=88);
       
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.