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


619

สมมติว่าฉันมีรหัสนี้:

var myArray = new Object();
myArray["firstname"] = "Bob";
myArray["lastname"] = "Smith";
myArray["age"] = 25;

ตอนนี้ถ้าฉันต้องการที่จะลบ "นามสกุล"? .... มีอะไรที่เทียบเท่ากัน
myArray["lastname"].remove()บ้าง

(ฉันต้องการองค์ประกอบหายไปเพราะจำนวนองค์ประกอบมีความสำคัญและฉันต้องการรักษาสิ่งต่าง ๆ ให้สะอาด)


27
เคล็ดลับ: อย่าทำให้อาร์เรย์และแผนที่สับสน บางภาษาเช่น php มีวัตถุเดียวสำหรับทั้งสอง แม้ว่าคุณจะใช้ประเภทที่ถูกต้องที่นี่ (วัตถุใหม่ ()) ที่คุณตั้งชื่อว่า myArray มันเป็นเรื่องของมาตรฐานสำหรับ langugage
Juan Mendes

อย่าลืมว่าจาวาสคริปต์นั้นพิมพ์น้อยและทุกอย่างก็เป็นวัตถุ ดูคำตอบของซาอูลด้านล่าง
stevek

4
@StephanKristyn - จะแม่นยำ JS มีประเภท แต่ในแบบไดนามิกและอ่อนแอทาง ตัวอย่างเช่นในขณะที่ตัวแปรของมันไม่มีการพิมพ์ค่าของพวกเขาไม่ใช่ นั่นคือส่วนที่มีชีวิตชีวา อ่อนแสดงว่าการดำเนินงานระหว่างประเภทค่าที่แตกต่างกันไม่ได้กำหนดไว้อย่างเคร่งครัดและพึ่งพาการแปลงเบื้องหลัง ตัวอย่างเช่น"Test" + {};คำสั่ง JS ที่ถูกต้องสมบูรณ์
ซาอูล

คำตอบ:


1135

อ็อบเจกต์ในจาวาสคริปต์สามารถใช้เป็นอาเรย์แบบเชื่อมโยง, คีย์การแมป (คุณสมบัติ) กับค่าต่างๆ

ในการลบคุณสมบัติออกจากวัตถุใน JavaScript คุณใช้deleteโอเปอเรเตอร์:

const o = { lastName: 'foo' }
o.hasOwnProperty('lastName') // true
delete o['lastName']
o.hasOwnProperty('lastName') // false

โปรดทราบว่าเมื่อdeleteนำไปใช้กับคุณสมบัติดัชนีของArrayคุณจะสร้างอาร์เรย์ที่มีประชากรเบาบาง (เช่นอาร์เรย์ที่มีดัชนีหายไป)

เมื่อทำงานร่วมกับกรณีของArrayถ้าคุณไม่ต้องการที่จะสร้างอาร์เรย์ประชากรเบาบาง - และคุณมักจะทำไม่ได้ - แล้วคุณควรใช้หรือArray#spliceArray#pop

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

ใช้deleteประกอบการสามารถส่งผลกระทบต่อความสามารถในเครื่องยนต์ JavaScript เพื่อเพิ่มประสิทธิภาพ รหัส


18
delete myArray[0]นี้จะทำให้เกิดปัญหาหากใช้ในอินสแตนซ์อาร์เรย์วัตถุที่จะเอาเป็นองค์ประกอบที่มีอยู่เช่น ดูstackoverflow.com/a/9973592/426379และการลบองค์ประกอบอาร์เรย์
Saul

4
ปัญหาอะไรจะเกิดขึ้น?
Gottox

26
@Gottox - lengthคุณสมบัติของวัตถุ Array ยังคงไม่เปลี่ยนแปลง
ซาอูล

12
@ ซาอูล: จะมีปัญหาถ้าmyArrayใช้เป็นอาร์เรย์จริงๆ - แต่มันไม่ใช่ ( myArrayเป็นชื่อที่โชคร้าย) มันเป็นวัตถุ ดังนั้นในกรณีนี้deleteก็โอเค โปรดทราบว่าแม้ว่ามันจะถูกสร้างขึ้นnew Array()และใช้เป็นอาเรย์แบบเชื่อมโยงก็จะยังคงตกลง คำเตือนของคุณยังคงเป็นสิ่งที่ต้องระวังหากใช้อาร์เรย์จริง
johndodo

2
@johndodo - จริง นั่นคือเหตุผลที่ผมเริ่มแสดงความคิดเห็นครั้งแรกของฉันกับนี้จะทำให้เกิดปัญหาถ้าใช้กับอาร์เรย์เช่นวัตถุ ฉันยังคงต้องการวิธีที่ทำงานได้อย่างถูกต้องในทุกกรณีดูคำตอบของฉันด้านล่าง
ซาอูล

79

วัตถุทั้งหมดใน JavaScript ถูกนำมาใช้เป็น hashtables / เชื่อมโยงอาร์เรย์ ดังนั้นสิ่งต่อไปนี้เทียบเท่า:

alert(myObj["SomeProperty"]);
alert(myObj.SomeProperty);

และตามที่ระบุไว้แล้วคุณ "ลบ" คุณสมบัติออกจากวัตถุผ่านdeleteคำหลักซึ่งคุณสามารถใช้ได้สองวิธี:

delete myObj["SomeProperty"];
delete myObj.SomeProperty;

หวังว่าข้อมูลเพิ่มเติมจะช่วย ...


10
ควรสังเกตว่าเครื่องหมายจุดไม่ทำงานหากคุณสมบัติไม่ใช่คำศัพท์ที่ง่าย ie myObj['some;property']ทำงานได้ แต่myObj.some;propertyจะไม่ (ด้วยเหตุผลที่ชัดเจน) นอกจากนี้อาจไม่ชัดเจนว่าคุณสามารถใช้ตัวแปรในรูปแบบวงเล็บปีกกาได้เช่นกันvar x = 'SomeProperty'; alert(myObj[x])
Kip

2
"วัตถุทั้งหมดใน JavaScript ถูกนำมาใช้เป็น hashtables / เชื่อมโยงอาร์เรย์" - เท็จ V8 ชอบเก็บวัตถุเป็นคลาสที่ซ่อน + ฟิลด์ที่อัดแน่น เฉพาะในกรณีที่คุณทำสิ่งแปลก ๆ ให้กับพวกเขา (เช่นการลบฟิลด์) มันจะยอมแพ้และใช้แผนที่แฮชเบื้องหลัง
John Dvorak

4
@JanDvorak - เฮ้คุณจำได้ไหมว่าคำตอบนี้ถูกเขียนครั้งแรกใช่มั้ย? คำอธิบายนั้นและยังเพียงพอสำหรับวัตถุประสงค์ส่วนใหญ่ ที่กล่าวว่าฉันเข้าใจว่าเป็นคนอวดรู้น่าเบื่อ :)
Jason Bunting

41

ไม่มีคำตอบก่อนที่อยู่ที่ความจริงที่ว่าจาวาสคริปต์ไม่ได้มีการเชื่อมโยงอาร์เรย์จะเริ่มต้นด้วย - ไม่มีประเภทเช่นดูarraytypeof

สิ่งที่ Javascript มีคืออินสแตนซ์ของวัตถุที่มีคุณสมบัติแบบไดนามิก เมื่อคุณสมบัติสับสนกับองค์ประกอบของอินสแตนซ์ของวัตถุ Array ดังนั้น Bad Things ™จะเกิดขึ้น:

ปัญหา

var elements = new Array()

elements.push(document.getElementsByTagName("head")[0])
elements.push(document.getElementsByTagName("title")[0])
elements["prop"] = document.getElementsByTagName("body")[0]

console.log("number of elements: ", elements.length)   // returns 2
delete elements[1]
console.log("number of elements: ", elements.length)   // returns 2 (?!)

for (var i = 0; i < elements.length; i++)
{
   // uh-oh... throws a TypeError when i == 1
   elements[i].onmouseover = function () { window.alert("Over It.")}
   console.log("success at index: ", i)
}

สารละลาย

ในการมีฟังก์ชั่นการลบอเนกประสงค์ที่ไม่ทำให้คุณระเบิดให้ใช้:

Object.prototype.removeItem = function (key) {
   if (!this.hasOwnProperty(key))
      return
   if (isNaN(parseInt(key)) || !(this instanceof Array))
      delete this[key]
   else
      this.splice(key, 1)
};

//
// Code sample.
//
var elements = new Array()

elements.push(document.getElementsByTagName("head")[0])
elements.push(document.getElementsByTagName("title")[0])
elements["prop"] = document.getElementsByTagName("body")[0]

console.log(elements.length)                        // returns 2
elements.removeItem("prop")
elements.removeItem(0)
console.log(elements.hasOwnProperty("prop"))        // returns false as it should
console.log(elements.length)                        // returns 1 as it should

8
วิธีการแก้ปัญหานี้มีสองประเด็น: มันซ่อนข้อเท็จจริงที่ว่าอาร์เรย์และวัตถุเป็นสัตว์ที่แตกต่างกันอย่างสิ้นเชิงใน JS (คุณรู้ แต่เห็นได้ชัดว่า OP ไม่ได้) และใช้ต้นแบบ OP น่าจะดีกว่าถ้าเขาเรียนรู้เกี่ยวกับอาร์เรย์และวัตถุ (และจะตั้งชื่อตัวแปรของเขาตามนั้น) - การพยายามซ่อนความแตกต่างระหว่างทั้งสองจะทำให้เขามีปัญหามากขึ้นเท่านั้น IMHO แน่นอน
johndodo

1
@johndodo - ทั้งหมดArrayใน JS เป็นวัตถุลองtypeof new Array();หรือtypeof []ยืนยัน Arrayเป็นเพียงวัตถุชนิดหนึ่งและไม่ใช่สัตว์ "ที่แตกต่าง" ใน JS วัตถุมีความโดดเด่นโดยใช้ชื่อคอนสตรัคของพวกเขาและห่วงโซ่ต้นแบบให้ดูที่การเขียนโปรแกรมต้นแบบตาม
ซาอูล

9
คุณไม่มีจุด ฉันรู้ว่าอาร์เรย์เป็นวัตถุด้วย แต่นั่นไม่ได้หมายความว่าควรใช้มันเป็นอย่างนั้น โปรแกรมเมอร์ควรตัดสินใจว่าเขาต้องการใช้อะไรเป็นอาร์เรย์ (พร้อมพุช, ป๊อป, [], ... ) หรือเป็นวัตถุ / "เชื่อมโยงอาเรย์" การผสมผสานและการจับคู่ไม่ใช่สูตรที่ดีเพราะปัญหาที่ทางออกของคุณพยายามซ่อน หากคุณตัดสินใจล่วงหน้าว่าจะใช้รูปแบบการออกแบบใด (อาร์เรย์หรือวัตถุ) จะไม่มีปัญหาดังกล่าว
johndodo

7
@johndodo - คุณกำลังพูดถึงปัญหาอะไรโดยเฉพาะ? จุดประสงค์ของรหัสข้างต้นคือเพื่อให้deleteผู้ประกอบการขาดได้Arrayโดยการให้ฟังก์ชั่น polymorphic อย่างง่าย
ซาอูล

1
deleteไม่มีข้อบกพร่อง deleteถูกออกแบบมาเพื่อลบคุณสมบัติ แค่นั้นแหละ. การใช้ตัวดำเนินการลบกับดัชนีของอาร์เรย์จะลบดัชนีนั้น ต้องทำอะไรอีก คุณเหลือด้วยชุดเบาบางซึ่งเป็นคุณสมบัติของภาษา หากคุณไม่ต้องการอาร์เรย์เบาบางไม่ลบดัชนี: การใช้งานหรือsplice pop
Ben Aston

35

เพียงลบวัตถุที่ลบ แต่ยังคงความยาวของอาร์เรย์เหมือนกัน

หากต้องการลบคุณต้องทำสิ่งต่อไปนี้:

array.splice(index, 1);

11
อันที่จริง แต่ในกรณีนี้ไม่ได้ใช้อาร์เรย์เพียงวัตถุเก่าธรรมดาดังนั้นจึงไม่มีความยาวหรือวิธีการประกบกัน
MooGoo

2
@Andreaa Panagiotidis ยกเว้นเมื่อเราไม่ได้พูดถึงอาร์เรย์ซึ่งในกรณีนี้มันผิด 100% ของเวลา🙂
Drenai

17

แม้ว่าคำตอบที่ยอมรับนั้นถูกต้อง แต่ก็ไม่มีคำอธิบายว่าทำไมมันจึงใช้งานได้

ก่อนอื่นรหัสของคุณควรสะท้อนถึงความจริงที่ว่านี่ไม่ใช่อาร์เรย์:

var myObject = new Object();
myObject["firstname"] = "Bob";
myObject["lastname"] = "Smith";
myObject["age"] = 25;

โปรดทราบว่าวัตถุทั้งหมด (รวมถึงArray) สามารถใช้วิธีนี้ได้ อย่างไรก็ตามอย่าคาดหวังว่าฟังก์ชั่นอาเรย์ JS มาตรฐาน (ป๊อปพุช ... ) จะทำงานกับวัตถุได้!

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

delete myObject["lastname"]

คุณควรตัดสินใจว่าจะใช้เส้นทางใด - ใช้วัตถุ (เชื่อมโยง / พจนานุกรม) หรือใช้อาร์เรย์ (แผนที่) อย่าผสมสองอย่างเข้าด้วยกัน


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

6

ใช้วิธีspliceการลบรายการออกจากอาร์เรย์วัตถุอย่างสมบูรณ์:

Object.prototype.removeItem = function (key, value) {
    if (value == undefined)
        return;

    for (var i in this) {
        if (this[i][key] == value) {
            this.splice(i, 1);
        }
    }
};

var collection = [
    { id: "5f299a5d-7793-47be-a827-bca227dbef95", title: "one" },
    { id: "87353080-8f49-46b9-9281-162a41ddb8df", title: "two" },
    { id: "a1af832c-9028-4690-9793-d623ecc75a95", title: "three" }
];

collection.removeItem("id", "87353080-8f49-46b9-9281-162a41ddb8df");

1
นี่เป็นวิธีการแก้ปัญหาทั่วไปเพิ่มเติมสามารถเพิ่มลงในไฟล์ js ของคุณและวิธีการจะสามารถใช้ได้กับทุกอาร์เรย์ไม่ใช่แค่หนึ่งอาร์เรย์
ฮุสเซน

6

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

หากคุณมีอาร์เรย์และไม่ใช่วัตถุคุณสามารถใช้ฟังก์ชัน. filterของอาร์เรย์เพื่อส่งคืนอาร์เรย์ใหม่โดยไม่มีรายการที่คุณต้องการลบออก:

var myArray = ['Bob', 'Smith', 25];
myArray = myArray.filter(function(item) {
    return item !== 'Smith';
});

หากคุณมีเบราว์เซอร์ที่เก่ากว่าและ jQuery jQuery มี$.grepวิธีการที่คล้ายกัน:

myArray = $.grep(myArray, function(item) {
    return item !== 'Smith';
});

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


5

คุณกำลังใช้ Object คุณไม่มีอาเรย์เชื่อมโยงที่จะเริ่มต้นด้วย ด้วยอาเรย์แบบเชื่อมโยงการเพิ่มและการลบรายการจะเป็นดังนี้:

    Array.prototype.contains = function(obj) 
    {
        var i = this.length;
        while (i--) 
        {
            if (this[i] === obj) 
            {
                return true;
            }
        }
        return false;
    }


    Array.prototype.add = function(key, value) 
    {
        if(this.contains(key))
            this[key] = value;
        else
        {
            this.push(key);
            this[key] = value;
        }
    }


    Array.prototype.remove = function(key) 
    {
        for(var i = 0; i < this.length; ++i)
        {
            if(this[i] == key)
            {
                this.splice(i, 1);
                return;
            }
        }
    }



    // Read a page's GET URL variables and return them as an associative array.
    function getUrlVars()
    {
        var vars = [], hash;
        var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');

        for(var i = 0; i < hashes.length; i++)
        {
            hash = hashes[i].split('=');
            vars.push(hash[0]);
            vars[hash[0]] = hash[1];
        }

        return vars;
    }



    function ForwardAndHideVariables() {
        var dictParameters = getUrlVars();

        dictParameters.add("mno", "pqr");
        dictParameters.add("mno", "stfu");

        dictParameters.remove("mno");



        for(var i = 0; i < dictParameters.length; i++)
        {
            var key = dictParameters[i];
            var value = dictParameters[key];
            alert(key + "=" + value);
        }
        // And now forward with HTTP-POST
        aa_post_to_url("Default.aspx", dictParameters);
    }


    function aa_post_to_url(path, params, method) {
        method = method || "post";

        var form = document.createElement("form");

        //move the submit function to another variable
        //so that it doesn't get written over if a parameter name is 'submit'
        form._submit_function_ = form.submit;

        form.setAttribute("method", method);
        form.setAttribute("action", path);

        for(var i = 0; i < params.length; i++)
        {
            var key = params[i];

            var hiddenField = document.createElement("input");
            hiddenField.setAttribute("type", "hidden");
            hiddenField.setAttribute("name", key);
            hiddenField.setAttribute("value", params[key]);

            form.appendChild(hiddenField);
        }

        document.body.appendChild(form);
        form._submit_function_(); //call the renamed function
    }

4

คุณสามารถลบรายการออกจากแผนที่ของคุณโดยกำหนดให้ชัดเจนเป็น 'ไม่ได้กำหนด' เช่นเดียวกับในกรณีของคุณ:

myArray ["นามสกุล"] = ไม่ได้กำหนด;


สิ่งนี้อาจเป็นประโยชน์ในกรณีที่ไม่มีใครแน่ใจว่ามีคีย์อยู่ในพจนานุกรมหรือไม่ แก้ไขฉันถ้าฉันผิด Amytis
Hassan Baig

3

หากไม่ว่าด้วยเหตุผลใดก็ตามคีย์ลบจะไม่ทำงาน (เหมือนว่ามันไม่ทำงานสำหรับฉัน)

คุณสามารถแบ่งออกแล้วกรองค่าที่ไม่ได้กำหนด

// to cut out one element via arr.splice(indexToRemove, numberToRemove);
array.splice(key, 1)
array.filter(function(n){return n});

อย่าพยายามและเชื่อมโยงพวกเขาตั้งแต่ประกบกันคืนองค์ประกอบที่ลบออก


3

เราสามารถใช้เป็นฟังก์ชั่นได้เช่นกัน เชิงมุมพ่นข้อผิดพลาดบางอย่างถ้าใช้เป็นต้นแบบ ขอบคุณ @HarpyWar มันช่วยฉันแก้ปัญหา

var removeItem = function (object, key, value) {
    if (value == undefined)
        return;

    for (var i in object) {
        if (object[i][key] == value) {
            object.splice(i, 1);
        }
    }
};

var collection = [
    { id: "5f299a5d-7793-47be-a827-bca227dbef95", title: "one" },
    { id: "87353080-8f49-46b9-9281-162a41ddb8df", title: "two" },
    { id: "a1af832c-9028-4690-9793-d623ecc75a95", title: "three" }
];

removeItem(collection, "id", "87353080-8f49-46b9-9281-162a41ddb8df");


1

โดยใช้"delete"คำหลักมันจะลบองค์ประกอบอาร์เรย์จากอาร์เรย์ในจาวาสคริปต์

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

พิจารณาข้อความต่อไปนี้

var arrayElementToDelete = new Object();

arrayElementToDelete["id"]           = "XERTYB00G1"; 
arrayElementToDelete["first_name"]   = "Employee_one";
arrayElementToDelete["status"]       = "Active"; 

delete arrayElementToDelete["status"];

บรรทัดสุดท้ายของรหัสจะลบองค์ประกอบอาร์เรย์ที่สำคัญคือ "สถานะ" ออกจากอาร์เรย์


0
var myArray = newmyArray = new Object(); 
myArray["firstname"] = "Bob";
myArray["lastname"] = "Smith";
myArray["age"] = 25;

var s = JSON.stringify(myArray);

s.replace(/"lastname[^,}]+,/g,'');
newmyArray = JSON.parse(p);

เราจะได้ผลลัพธ์เดียวกันโดยไม่วนซ้ำ / วนซ้ำ


0

สำหรับ "อาร์เรย์":

หากคุณรู้ว่าดัชนี:

array.splice(index, 1);

ถ้าคุณรู้คุณค่า:

function removeItem(array, value) {
    var index = array.indexOf(value);
    if (index > -1) {
        array.splice(index, 1);
    }
    return array;
}

คำตอบ upvoted ที่สุดสำหรับการdeleteทำงานได้ดีในกรณีของวัตถุ แต่ไม่ใช่สำหรับอาร์เรย์จริง ถ้าฉันใช้deleteมันจะลบองค์ประกอบออกจากลูป แต่จะรักษาองค์ประกอบที่เป็นemptyและความยาวของอาร์เรย์จะไม่เปลี่ยนแปลง นี่อาจเป็นปัญหาในบางสถานการณ์

ตัวอย่างเช่นถ้าฉันทำ myArray.toString () ใน myArray หลังจากลบผ่านdeleteมันจะสร้างรายการที่ว่างเปล่าเช่น ,,


0

วิธีการทำงานสำหรับฉันเท่านั้น:

function removeItem (array, value) {
    var i = 0;
    while (i < array.length) {
        if(array[i] === value) {
            array.splice(i, 1);
        } else {
            ++i;
        }
    }
    return array;
}

การใช้งาน:

var new = removeItem( ["apple","banana", "orange"],  "apple");
// ---> ["banana", "orange"]

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