การลบองค์ประกอบอาร์เรย์ใน JavaScript - ลบ vs splice


1334

ความแตกต่างระหว่างการใช้คืออะไรผู้ประกอบการในองค์ประกอบอาร์เรย์เป็นเทียบกับการใช้วิธี ?deleteArray.splice

ตัวอย่างเช่น:

myArray = ['a', 'b', 'c', 'd'];

delete myArray[1];
//  or
myArray.splice (1, 1);

ทำไมถึงมีวิธีการประกบกันถ้าฉันสามารถลบองค์ประกอบอาร์เรย์อย่างที่ฉันสามารถทำได้กับวัตถุ


3
สำหรับ.spliceในลูปได้ดูที่คำถามนี้: ลบจาก array ใน JavaScript
Rob W

6
@andynormancx ใช่ แต่คำตอบนี้โพสต์เพียงไม่กี่วันหลังจากนั้นและได้รับคะแนนเสียงมากขึ้น - ฉันบอกว่ามันเขียนได้ดีกว่านั่นต้องเป็นอย่างนั้น
Camilo Martin

@andynormancx - ดูเหมือนจะไม่ซ้ำกันแน่นอน คำถามที่คุณเชื่อมโยงนั้นเป็นพื้นถามว่าทำไมการลบองค์ประกอบจากอาร์เรย์ (จึงทำให้เบาบาง) จะไม่ลดความยาวของมัน คำถามนี้จะขอความแตกต่างระหว่างและdelete Array.prototype.splice
chharvey

@chharvey เห็นด้วยที่สำคัญกว่านั้นคำถามนี้จะถูกโพสต์เมื่อ 9 ปีที่แล้วได้อย่างไร! ทำให้ฉันรู้สึกแก่ตัวที่จะกลับมาที่นี่เพื่อแสดงความคิดเห็นเกี่ยวกับมัน
andynormancx

คำตอบ:


1693

deleteจะลบคุณสมบัติของวัตถุ แต่จะไม่ทำดัชนีอาร์เรย์ใหม่หรืออัพเดตความยาว สิ่งนี้ทำให้ดูเหมือนว่าไม่ได้กำหนดไว้:

> myArray = ['a', 'b', 'c', 'd']
  ["a", "b", "c", "d"]
> delete myArray[0]
  true
> myArray[0]
  undefined

โปรดทราบว่าในความเป็นจริงไม่ได้ตั้งค่าเป็นค่าundefinedแต่คุณสมบัติจะถูกลบออกจากอาร์เรย์ทำให้ดูเหมือนไม่ได้กำหนด เครื่องมือ dev ของ Chrome ทำให้ความแตกต่างนี้ชัดเจนโดยการพิมพ์emptyเมื่อบันทึกอาร์เรย์

> myArray[0]
  undefined
> myArray
  [empty, "b", "c", "d"]

myArray.splice(start, deleteCount) ลบองค์ประกอบจริงทำดัชนีอาร์เรย์และเปลี่ยนความยาวของมัน

> myArray = ['a', 'b', 'c', 'd']
  ["a", "b", "c", "d"]
> myArray.splice(0, 2)
  ["a", "b"]
> myArray
  ["c", "d"]

74
อันที่จริงdelete จะลบองค์ประกอบ แต่ไม่ได้ทำดัชนีใหม่หรือปรับปรุงความยาวของมัน (ซึ่งจะถูกบอกเป็นนัยโดยอดีตเพราะความยาวมักจะเป็นดัชนีสูงสุด + 1)
เฟลิกซ์คลิง

3
JSlint ไม่ชอบdelete myArray[0]คำว่า " ผู้ดำเนินการที่คาดหวังและเห็น 'ลบ' แทน " spliceแนะนำให้ใช้
ตา

21
@Eye: จริง ๆ แล้ว JSLint เป็นเพียงแค่บ่นเกี่ยวกับการขาดเครื่องหมายอัฒภาคในบรรทัดก่อนหน้า และคุณไม่สามารถแนะนำสิ่งใดสิ่งหนึ่งได้เพราะพวกเขาทำสิ่งที่แตกต่างอย่างสิ้นเชิง ...
Ry-

3
"ลบในกรณีนี้จะตั้งค่าองค์ประกอบเป็นไม่ได้กำหนด:"ไม่นั่นไม่ถูกต้อง มีความแตกต่างพื้นฐานระหว่างและdelete myArray[0] myArray[0] = undefinedในกรณีก่อนหน้าคุณสมบัติจะถูกลบออกจากวัตถุอาร์เรย์ทั้งหมด undefinedในกรณีที่สองคุณสมบัติที่ยังคงมีค่า
TJ Crowder

1
FYI นี้ Chrome เครื่องมือ dev แสดงให้เห็นว่าคำหลักemptyแทนการundefinedที่จะปรับปรุงความแตกต่างระหว่างลบจริง (หรือ uninitialized) undefinedองค์ประกอบอาร์เรย์เมื่อเทียบกับองค์ประกอบที่มีมูลค่าที่แท้จริงของนั้น โปรดทราบว่าตามที่ฉันพูดสิ่งนี้ฉันหมายความว่าจะแสดงเป็นemptyเท่านั้นและไม่ได้อ้างถึงมูลค่าจริงที่เรียกว่าempty(ซึ่งไม่มีอยู่จริง)
chharvey

340

Array.remove () วิธีการ

John Resigผู้สร้าง jQuery สร้างArray.removeวิธีที่สะดวกมากที่ฉันมักจะใช้มันในโครงการของฉัน

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

และนี่คือตัวอย่างของวิธีใช้:

// Remove the second item from the array
array.remove(1);
// Remove the second-to-last item from the array
array.remove(-2);
// Remove the second and third items from the array
array.remove(1,2);
// Remove the last and second-to-last items from the array
array.remove(-2,-1);

เว็บไซต์ของ John


4
+1 สำหรับ Array.remove () อย่างไรก็ตามมันไม่มีความสุขที่ถูกส่งผ่านอาร์กิวเมนต์ของสตริง (ซึ่งแตกต่างจากวิธี Array ส่วนใหญ่เช่น[1,2,3].slice('1'); // =[2,3]) ดังนั้นจึงปลอดภัยกว่าที่จะเปลี่ยนเป็นvar rest = this.slice(parseInt(to || from) + 1 || this.length);
Richard Inglis

1
@tomwrong ไม่มีเธรดใน javascript และฟังก์ชันดำเนินการthis.push.apply(this, rest)จากนั้นส่งคืนค่าที่ส่งคืน
billy

59
นี่ไม่ได้ตอบคำถามเลย
Ry-

16
ทำไมไม่ใช้แค่ประกบกัน ()? ชื่อของฟังก์ชันนี้ชื่อพารามิเตอร์และผลลัพธ์ไม่ชัดเจน คำแนะนำของฉันคือใช้เพียงรอยต่อ (ดัชนีความยาว) - (ดูคำตอบของ Andy Hume)
auco

3
ฟังก์ชั่นที่ให้ไว้ข้างต้นทำงานตามที่อธิบายไว้ แต่มันสร้างผลข้างเคียงที่ไม่พึงประสงค์เมื่อวนซ้ำผ่านอาร์เรย์พร้อมfor(var i in array)วง ฉันลบมันแล้วใช้รอยต่อแทน
alexykot

104

เนื่องจากการลบจะลบวัตถุออกจากองค์ประกอบในอาร์เรย์เท่านั้นความยาวของอาร์เรย์จึงไม่เปลี่ยนแปลง Splice จะลบวัตถุและทำให้อาร์เรย์สั้นลง

รหัสต่อไปนี้จะแสดง "a", "b", "undefined", "d"

myArray = ['a', 'b', 'c', 'd']; delete myArray[2];

for (var count = 0; count < myArray.length; count++) {
    alert(myArray[count]);
}

โดยที่สิ่งนี้จะแสดง "a", "b", "d"

myArray = ['a', 'b', 'c', 'd']; myArray.splice(2,1);

for (var count = 0; count < myArray.length; count++) {
    alert(myArray[count]);
}

11
ตัวอย่างที่ดียกเว้นความกำกวมในตัวอย่างที่สองโดยใช้ 1,1 - 1 ตัวแรกหมายถึงดัชนีในอาเรย์เพื่อเริ่มต้นประกบกัน 1 ที่สองคือจำนวนองค์ประกอบที่จะลบ ดังนั้นในการลบ 'c' ออกจากอาร์เรย์เดิมให้ใช้myArray.splice(2,1)
iancoleman

68

ฉันสะดุดกับคำถามนี้ในขณะที่พยายามทำความเข้าใจวิธีลบองค์ประกอบที่เกิดขึ้นจาก Array นี่คือการเปรียบเทียบของspliceและdeleteสำหรับการลบทุก'c'จากitemsอาร์เรย์

var items = ['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd'];

while (items.indexOf('c') !== -1) {
  items.splice(items.indexOf('c'), 1);
}

console.log(items); // ["a", "b", "d", "a", "b", "d"]

items = ['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd'];

while (items.indexOf('c') !== -1) {
  delete items[items.indexOf('c')];
}

console.log(items); // ["a", "b", undefined, "d", "a", "b", undefined, "d"]


14

จากการอ้างอิง Core JavaScript 1.5> ตัวดำเนินการ> ตัวดำเนินการพิเศษ> ลบตัวดำเนินการ :

เมื่อคุณลบองค์ประกอบอาร์เรย์ความยาวของอาร์เรย์จะไม่ได้รับผลกระทบ ตัวอย่างเช่นหากคุณลบ [3], [4] จะยังคงเป็น [4] และ [3] จะไม่ถูกกำหนด สิ่งนี้จะเก็บไว้แม้ว่าคุณจะลบองค์ประกอบสุดท้ายของอาร์เรย์ (ลบ [a.length-1])


10

splice จะทำงานกับดัชนีตัวเลข

ในขณะที่deleteสามารถใช้กับดัชนีชนิดอื่น ..

ตัวอย่าง:

delete myArray['text1'];

9
เมื่อคุณพูดว่า 'ดัชนีชนิดอื่น' คุณจะไม่พูดถึงอาร์เรย์อีกต่อไป แต่จะเป็นวัตถุซึ่งเป็นสิ่งที่ OP กำลังถาม
Yi Jiang

2
@YiJiang: อาร์เรย์เป็นวัตถุ สิ่งบ่งชี้คือคุณสมบัติ ไม่มีความแตกต่าง
Bergi

9

มันอาจจะคุ้มค่าที่จะกล่าวถึงว่า splice ใช้งานได้กับอาร์เรย์เท่านั้น (คุณสมบัติของออบเจ็กต์ไม่สามารถเชื่อถือได้เพื่อติดตามลำดับที่สอดคล้องกัน

ในการลบคู่คีย์ - ค่าออกจากวัตถุการลบคือสิ่งที่คุณต้องการ:

delete myObj.propName;     // , or:
delete myObj["propName"];  // Equivalent.

การลบไม่ได้เรียงลำดับคีย์อาร์เรย์อีกครั้งดังนั้น: var arr = [1,2,3,4,5]; ลบ arr [3]; สำหรับ (var i = 0; i <= arr.length; i ++) console.log (arr [i]); จะแสดงผลลัพธ์ที่ไม่คาดคิด
Kristian Williams

นี่เป็นเรื่องจริง ดังนั้นหากคุณไม่ต้องการทิ้งรายการที่ไม่ได้กำหนดไว้ในที่ตั้งนั้นอย่าใช้ลบในคีย์ของแถวลำดับ! ฉันเพิ่มความคิดเห็นนี้เพื่อรวมการอ้างอิงของการใช้งานที่ถูกต้องของการลบ
jtrick

แต่ทำไมการลบจะส่งผลที่ไม่คาดคิด?
อเล็กซ์

9

ลบ Vs splice

เมื่อคุณลบรายการออกจากอาร์เรย์

var arr = [1,2,3,4]; delete arr[2]; //result [1, 2, 3:, 4]
console.log(arr)

เมื่อคุณประกบกัน

var arr = [1,2,3,4]; arr.splice(1,1); //result [1, 3, 4]
console.log(arr);

ในกรณีของการลบองค์ประกอบจะถูกลบออกแต่ดัชนียังคงว่างเปล่า

ในขณะที่ในกรณีขององค์ประกอบรอยต่อจะถูกลบและดัชนีขององค์ประกอบที่เหลือจะลดลงตามลำดับ


8

ตามที่ระบุไว้ข้างต้นหลายครั้งการใช้งานsplice()ดูเหมือนว่าเหมาะสมอย่างสมบูรณ์แบบ เอกสารที่ Mozilla:

splice()วิธีการเปลี่ยนแปลงเนื้อหาของอาร์เรย์โดยการเอาองค์ประกอบที่มีอยู่และ / หรือการเพิ่มองค์ประกอบใหม่

var myFish = ['angel', 'clown', 'mandarin', 'sturgeon'];

myFish.splice(2, 0, 'drum'); 
// myFish is ["angel", "clown", "drum", "mandarin", "sturgeon"]

myFish.splice(2, 1); 
// myFish is ["angel", "clown", "mandarin", "sturgeon"]

วากยสัมพันธ์

array.splice(start)
array.splice(start, deleteCount)
array.splice(start, deleteCount, item1, item2, ...)

พารามิเตอร์

เริ่มต้น

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

deleteCount

จำนวนเต็มที่ระบุจำนวนองค์ประกอบอาร์เรย์เก่าที่จะลบ หาก deleteCount เป็น 0 จะไม่มีการลบองค์ประกอบใด ๆ ในกรณีนี้คุณควรระบุองค์ประกอบใหม่อย่างน้อยหนึ่งองค์ประกอบ หาก deleteCount มากกว่าจำนวนขององค์ประกอบที่เหลือในอาร์เรย์เริ่มต้นที่เริ่มต้นแล้วองค์ประกอบทั้งหมดที่ผ่านมาในตอนท้ายของอาร์เรย์จะถูกลบ

หากไม่ได้ระบุ deleteCount, deleteCount จะเท่ากับ (arr.length - start).

รายการ 1, รายการ 2, ...

องค์ประกอบที่จะเพิ่มในอาร์เรย์เริ่มต้นที่ดัชนีเริ่มต้น หากคุณไม่ได้ระบุองค์ประกอบใด ๆsplice()จะลบองค์ประกอบออกจากอาร์เรย์เท่านั้น

ค่าส่งคืน

อาร์เรย์ที่มีองค์ประกอบที่ถูกลบ หากลบองค์ประกอบเดียวเท่านั้นอาร์เรย์ขององค์ประกอบหนึ่งจะถูกส่งคืน หากไม่มีองค์ประกอบใดถูกลบออกอาร์เรย์ว่างจะถูกส่งคืน

[ ... ]


@downvoter: ทำไม downvote สนใจที่จะอธิบายหรือไม่?
serv-inc

7

การลบทำหน้าที่เหมือนสถานการณ์ในโลกแห่งความจริงมันเพิ่งลบรายการออก แต่ความยาวของอาร์เรย์ยังคงเท่าเดิม:

ตัวอย่างจากโหนดเทอร์มินัล:

> var arr = ["a","b","c","d"];
> delete arr[2]
true
> arr
[ 'a', 'b', , 'd', 'e' ]

นี่คือฟังก์ชั่นในการลบรายการของอาเรย์โดยดัชนีโดยใช้slice ()มันจะใช้เวลา arr เป็น ARG แรกและดัชนีของสมาชิกที่คุณต้องการลบเป็นอาร์กิวเมนต์ที่สอง อย่างที่คุณเห็นจริง ๆ แล้วมันจะลบสมาชิกของอาร์เรย์และจะลดความยาวของอาร์เรย์ลง 1

function(arr,arrIndex){
    return arr.slice(0,arrIndex).concat(arr.slice(arrIndex + 1));
}

สิ่งที่ฟังก์ชั่นด้านบนทำคือนำสมาชิกทั้งหมดขึ้นกับดัชนีและสมาชิกทุกคนหลังจากดัชนีและเชื่อมต่อพวกเขาเข้าด้วยกันและส่งกลับผลลัพธ์

นี่คือตัวอย่างการใช้ฟังก์ชั่นด้านบนเป็นโมดูลโหนดการเห็นเทอร์มินัลจะมีประโยชน์:

> var arr = ["a","b","c","d"]
> arr
[ 'a', 'b', 'c', 'd' ]
> arr.length
4 
> var arrayRemoveIndex = require("./lib/array_remove_index");
> var newArray = arrayRemoveIndex(arr,arr.indexOf('c'))
> newArray
[ 'a', 'b', 'd' ] // c ya later
> newArray.length
3

โปรดทราบว่าสิ่งนี้จะไม่ทำงานหนึ่งอาเรย์ที่มี dupes อยู่ในนั้นเพราะ indexOf ("c") เพิ่งจะได้รับการทดสอบครั้งแรกและแยกออกและเอา "c" แรกที่พบ


6

หากคุณต้องการวนซ้ำอาร์เรย์ขนาดใหญ่และลบองค์ประกอบที่เลือกจะมีราคาแพงที่จะเรียก splice () สำหรับการลบทุกครั้งเนื่องจาก splice () จะต้องสร้างดัชนีองค์ประกอบที่ตามมาใหม่ทุกครั้ง เนื่องจากอาร์เรย์มีการเชื่อมโยงใน Javascript มันจะมีประสิทธิภาพมากกว่าในการลบองค์ประกอบแต่ละรายการจากนั้นทำดัชนีอาร์เรย์อีกครั้งในภายหลัง

คุณสามารถทำได้โดยการสร้างอาร์เรย์ใหม่ เช่น

function reindexArray( array )
{
       var result = [];
        for( var key in array )
                result.push( array[key] );
        return result;
};

แต่ฉันไม่คิดว่าคุณสามารถแก้ไขค่าคีย์ในอาเรย์ดั้งเดิมซึ่งจะมีประสิทธิภาพมากขึ้น - ดูเหมือนว่าคุณอาจต้องสร้างอาเรย์ใหม่

โปรดทราบว่าคุณไม่จำเป็นต้องตรวจสอบรายการ "ไม่ได้กำหนด" เนื่องจากไม่มีอยู่จริงและ for for loop ไม่ส่งคืน มันเป็นสิ่งประดิษฐ์ของการพิมพ์อาเรย์ที่แสดงว่าไม่ได้กำหนด ดูเหมือนว่าจะไม่มีอยู่ในหน่วยความจำ

มันจะดีถ้าคุณสามารถใช้บางอย่างเช่น slice () ซึ่งจะเร็วกว่า แต่ก็ไม่ได้จัดทำดัชนีใหม่ ใครรู้วิธีที่ดีกว่า


ที่จริงแล้วคุณสามารถทำได้ในสถานที่ดังต่อไปนี้ซึ่งอาจมีประสิทธิภาพมากขึ้นฉลาดขึ้น:

reindexArray : function( array )
{
    var index = 0;                          // The index where the element should be
    for( var key in array )                 // Iterate the array
    {
        if( parseInt( key ) !== index )     // If the element is out of sequence
        {
            array[index] = array[key];      // Move it to the correct, earlier position in the array
            ++index;                        // Update the index
        }
    }

    array.splice( index );  // Remove any remaining elements (These will be duplicates of earlier items)
},

ฉันเชื่อดัชนี ++; ต้องเกิดขึ้นนอก 'ถ้า' กำลังแก้ไข
mishal153

6

คุณสามารถใช้สิ่งนี้

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]


สิ่งนี้ง่ายกว่าsliceหากคุณมาจากพื้นหลังการใช้งาน (อาจมีประสิทธิภาพน้อยกว่า)
jethro

3

ทำไมไม่เพียงแค่กรอง? ฉันคิดว่ามันเป็นวิธีที่ชัดเจนที่สุดในการพิจารณาอาร์เรย์ใน js

myArray = myArray.filter(function(item){
    return item.anProperty != whoShouldBeDeleted
});

แล้วอาเรย์ที่มีหลายร้อย (ถ้าไม่นับพัน) ของเรคคอร์ดที่มีเพียง 3 ในนั้นจะต้องถูกลบออก?
Joel Hernandez

จุดดี. ฉันใช้วิธีนี้สำหรับอาร์เรย์เบาบางซึ่งมีความยาวไม่เกิน 200 หรือ 300 และทำงานได้ดีมาก อย่างไรก็ตามฉันคิดว่าควรเลือกไลบรารี่แบบขีดเส้นใต้ถ้าคุณต้องจัดการอาร์เรย์ที่ใหญ่กว่านี้
Asqan

1
อย่างไรก็ตามดูเหมือนดีกว่าdeleteหรือมากกว่าsliceสำหรับฉัน
Juneyoung Oh

3

ความแตกต่างสามารถมองเห็นได้โดยการบันทึกความยาวของแต่ละอาร์เรย์หลังจากใช้deleteตัวดำเนินการและsplice()วิธีการ ตัวอย่างเช่น:

ลบโอเปอเรเตอร์

var trees = ['redwood', 'bay', 'cedar', 'oak', 'maple'];
delete trees[3];

console.log(trees); // ["redwood", "bay", "cedar", empty, "maple"]
console.log(trees.length); // 5

deleteประกอบการเอาองค์ประกอบจากอาร์เรย์ แต่ "ยึด" ขององค์ประกอบยังคงมีอยู่ oakถูกลบแล้ว แต่ยังคงใช้พื้นที่ในอาร์เรย์ ด้วยเหตุนี้ความยาวของอาร์เรย์จึงเหลือ 5

วิธีการประกบกัน ()

var trees = ['redwood', 'bay', 'cedar', 'oak', 'maple'];
trees.splice(3,1);

console.log(trees); // ["redwood", "bay", "cedar", "maple"]
console.log(trees.length); // 4

splice()วิธีสมบูรณ์เอาค่าเป้าหมายและว่า "ยึด" ได้เป็นอย่างดี oakถูกลบเช่นเดียวกับพื้นที่ที่เคยครอบครองในอาร์เรย์ ความยาวของอาร์เรย์คือ 4


2
function remove_array_value(array, value) {
    var index = array.indexOf(value);
    if (index >= 0) {
        array.splice(index, 1);
        reindex_array(array);
    }
}
function reindex_array(array) {
   var result = [];
    for (var key in array) {
        result.push(array[key]);
    }
    return result;
}

ตัวอย่าง:

var example_arr = ['apple', 'banana', 'lemon'];   // length = 3
remove_array_value(example_arr, 'banana');

Banana ถูกลบและ array length = 2


2

พวกมันต่างกันที่มีจุดประสงค์ต่างกัน

spliceเฉพาะอาร์เรย์และเมื่อใช้สำหรับการลบจะลบรายการออกจากอาร์เรย์และย้ายรายการก่อนหน้าทั้งหมดขึ้นเพื่อเติมเต็มช่องว่าง (. นอกจากนี้ยังสามารถใช้ในการแทรกรายการหรือทั้งสองอย่างในเวลาเดียวกัน) spliceจะเปลี่ยนlengthของอาร์เรย์ (สมมติว่ามันไม่ได้มีการโทรไม่-op: theArray.splice(x, 0))

deleteไม่เฉพาะอาร์เรย์ มันถูกออกแบบมาเพื่อใช้กับวัตถุ: มันจะเอาคุณสมบัติ (คู่คีย์ / ค่า) ออกจากวัตถุที่คุณใช้ มันใช้กับอาร์เรย์เท่านั้นเพราะอาร์เรย์มาตรฐาน (เช่นไม่พิมพ์) ใน JavaScript ไม่ได้เป็นอาร์เรย์จริงๆเลย * เป็นวัตถุที่มีการจัดการพิเศษสำหรับคุณสมบัติบางอย่างเช่นที่มีชื่อเป็น "ดัชนีอาร์เรย์" (ซึ่งเป็นกำหนดชื่อสตริง "... ที่มีค่าตัวเลขที่iอยู่ในช่วง+0 ≤ i < 2^32-1") lengthและ เมื่อคุณใช้deleteเพื่อลบรายการอาร์เรย์สิ่งที่ทำคือลบรายการ มันไม่ย้ายรายการอื่น ๆ ที่ตามมาเพื่อเติมเต็มช่องว่างและดังนั้นอาร์เรย์จึงกลายเป็น "เบาบาง" (มีบางรายการหายไปโดยสิ้นเชิง) lengthมันมีผลกระทบต่อ

คู่ของคำตอบปัจจุบันสำหรับคำถามนี้อย่างไม่ถูกต้องระบุว่าการใช้delete"ตั้งค่ารายการเป็นundefined" ไม่ถูกต้อง มันลบรายการ (คุณสมบัติ) ทั้งหมดออกจากช่องว่าง

ลองใช้รหัสเพื่ออธิบายความแตกต่าง:

console.log("Using `splice`:");
var a = ["a", "b", "c", "d", "e"];
console.log(a.length);            // 5
a.splice(0, 1);
console.log(a.length);            // 4
console.log(a[0]);                // "b"

console.log("Using `delete`");
var a = ["a", "b", "c", "d", "e"];
console.log(a.length);            // 5
delete a[0];
console.log(a.length);            // still 5
console.log(a[0]);                // undefined
console.log("0" in a);            // false
console.log(a.hasOwnProperty(0)); // false

console.log("Setting to `undefined`");
var a = ["a", "b", "c", "d", "e"];
console.log(a.length);            // 5
a[0] = undefined;
console.log(a.length);            // still 5
console.log(a[0]);                // undefined
console.log("0" in a);            // true
console.log(a.hasOwnProperty(0)); // true


* (นั่นคือโพสต์ในบล็อกเล็ก ๆ ของฉันโลหิตจาง)


2

ขณะนี้มีสองวิธีในการทำเช่นนี้

  1. ใช้ประกบกัน ()

    arrayObject.splice(index, 1);

  2. โดยใช้การลบ

    delete arrayObject[index];

แต่ฉันมักจะแนะนำให้ใช้การต่อรอยสำหรับวัตถุอาร์เรย์และลบสำหรับคุณลักษณะของวัตถุเพราะลบไม่ได้ปรับปรุงความยาวของอาร์เรย์


1

ตกลงลองนึกภาพเรามีอาร์เรย์ด้านล่างนี้:

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

ลองลบก่อน:

delete arr[1];

และนี่คือผลลัพธ์:

[1, empty, 3, 4, 5];

ว่างเปล่า! และขอมัน:

arr[1]; //undefined

ดังนั้นหมายถึงเพียงแค่ค่าที่ถูกลบและมันไม่ได้ถูกกำหนดในขณะนี้ดังนั้นความยาวจึงเท่ากันมันจะคืนค่าจริง ...

ลองรีเซ็ตอาร์เรย์ของเราและทำมันด้วยประกบกันในครั้งนี้:

arr.splice(1, 1);

และนี่คือผลลัพธ์ในครั้งนี้:

[1, 3, 4, 5];

เมื่อคุณเห็นความยาวของอาเรย์เปลี่ยนไปและตอนนี้arr[1]เป็น3

นอกจากนี้จะส่งคืนรายการที่ถูกลบใน Array ซึ่ง[3]ในกรณีนี้ ...


1

คนอื่น ๆ ได้แล้วเมื่อเทียบอย่างถูกต้องด้วยdeletesplice

การเปรียบเทียบที่น่าสนใจอีกประการหนึ่งคือdeleteเมื่อเทียบกับundefined: รายการอาร์เรย์ที่ถูกลบใช้หน่วยความจำน้อยกว่ารายการที่เพิ่งตั้งค่าเป็นundefined;

ตัวอย่างเช่นรหัสนี้จะไม่เสร็จ:

let y = 1;
let ary = [];
console.log("Fatal Error Coming Soon");
while (y < 4294967295)
{
    ary.push(y);
    ary[y] = undefined;
    y += 1;
}
console(ary.length);

มันสร้างข้อผิดพลาดนี้:

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory.

ดังนั้นตามที่คุณเห็นundefinedจริง ๆ แล้วใช้หน่วยความจำกอง

อย่างไรก็ตามหากคุณdeleteใช้ ary-item แทนการตั้งค่าundefinedเป็นรหัสจะค่อยๆเสร็จสิ้น:

let x = 1;
let ary = [];
console.log("This will take a while, but it will eventually finish successfully.");
while (x < 4294967295)
{
    ary.push(x);
    ary[x] = undefined;
    delete ary[x];
    x += 1;
}
console.log(`Success, array-length: ${ary.length}.`);

นี่เป็นตัวอย่างที่ดี แต่พวกเขาพูดถึงเรื่องdeleteที่ฉันไม่เคยเห็นใครพูดถึงเลย


1

หากคุณมีอาร์เรย์ขนาดเล็กคุณสามารถใช้filter:

myArray = ['a', 'b', 'c', 'd'];
myArray = myArray.filter(x => x !== 'b');

0

วิธีที่ง่ายที่สุดน่าจะเป็น

var myArray = ['a', 'b', 'c', 'd'];
delete myArray[1]; // ['a', undefined, 'c', 'd']. Then use lodash compact method to remove false, null, 0, "", undefined and NaN
myArray = _.compact(myArray); ['a', 'c', 'd'];

หวังว่านี่จะช่วยได้ การอ้างอิง: https://lodash.com/docs#compact


1
หากมีคนสงสัยในเรื่องนี้compact... ไม่จำเป็นต้องพักอาศัย ลองmyArray.filter(function(n){return n;})
ดาด

0

สำหรับผู้ที่ต้องการใช้Lodashสามารถใช้: myArray = _.without(myArray, itemToRemove)

หรือตามที่ฉันใช้ใน Angular2

import { without } from 'lodash';
...
myArray = without(myArray, itemToRemove);
...

0

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

splice : เอาองค์ประกอบออกแล้วทำดัชนีอาร์เรย์อีกครั้งและเปลี่ยนความยาว

ลบองค์ประกอบจากครั้งสุดท้าย

arrName.pop();

ลบองค์ประกอบตั้งแต่แรก

arrName.shift();

ลบออกจากกลาง

arrName.splice(starting index,number of element you wnt to delete);

Ex: arrName.splice(1,1);

ลบองค์ประกอบหนึ่งจากครั้งสุดท้าย

arrName.splice(-1);

ลบโดยใช้หมายเลขดัชนีอาร์เรย์

 delete arrName[1];

0

หากองค์ประกอบที่ต้องการลบอยู่ตรงกลาง (บอกว่าเราต้องการลบ 'c' ซึ่งดัชนีของมันคือ 1) คุณสามารถใช้:

var arr = ['a','b','c'];
var indexToDelete = 1;
var newArray = arr.slice(0,indexToDelete).combine(arr.slice(indexToDelete+1, arr.length))

0

IndexOfยอมรับประเภทการอ้างอิงด้วย สมมติว่าสถานการณ์ต่อไปนี้:

var arr = [{item: 1}, {item: 2}, {item: 3}];
var found = find(2, 3); //pseudo code: will return [{item: 2}, {item:3}]
var l = found.length;

while(l--) {
   var index = arr.indexOf(found[l])
      arr.splice(index, 1);
   }
   
console.log(arr.length); //1

ที่แตกต่างกัน:

var item2 = findUnique(2); //will return {item: 2}
var l = arr.length;
var found = false;
  while(!found && l--) {
  found = arr[l] === item2;
}

console.log(l, arr[l]);// l is index, arr[l] is the item you look for

-1
function deleteFromArray(array, indexToDelete){
  var remain = new Array();
  for(var i in array){
    if(array[i] == indexToDelete){
      continue;
    }
    remain.push(array[i]);
  }
  return remain;
}

myArray = ['a', 'b', 'c', 'd'];
deleteFromArray(myArray , 0);

// result: myArray = ['b', 'c', 'd'];


@ChrisDennis ทำไม (ไม่มีการเสียดสีหรือเจตนาร้ายนี่เป็นคำถามที่จริงใจ)
Chris Bier

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