Javascript ilişkilendirilebilir dizisindeki nesneleri nasıl kaldırabilirim?


619

Bu kodun olduğunu varsayalım:

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

Şimdi "soyadı" kaldırmak istersem? .... bazı eşdeğer var
myArray["lastname"].remove()mı?

(Gittiğim öğeye ihtiyacım var çünkü öğe sayısı önemli ve işleri temiz tutmak istiyorum.)


27
Bir ipucu: dizileri ve haritaları karıştırmayın. Php gibi bazı diller, her ikisi için de tek bir nesneye sahiptir. Burada myArray adını verdiğiniz doğru türü (yeni Object ()) kullansanız da, bu sadece bir hata için standartlar meselesidir.
Juan Mendes

JavaScript'in türsüz olduğunu ve her şeyin bir nesne olduğunu unutmayın. Aşağıda Saul'un cevabına bakınız.
stevek

4
@StephanKristyn - kesin olmak gerekirse, JS'nin türleri vardır ancak dinamik ve zayıf bir şekilde. Örneğin, değişkenleri gerçekten de tipsiz olsa da, değerleri değildir. Yani dinamik parçası. Zayıf , farklı değer türleri arasındaki işlemlerin kesin olarak tanımlanmadığını ve sahne arkası dönüşümlerine dayandığını belirtir ; örneğin "Test" + {};, mükemmel şekilde geçerli bir JS ifadesidir.
Saul

Yanıtlar:


1135

JavaScript'teki nesneler, ilişkilendirilebilir diziler, anahtarları (özellikler) değerlerle eşleme olarak düşünülebilir.

JavaScript'teki bir nesneden bir özelliği kaldırmak için deleteişleci kullanırsınız :

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

Anının deletebir dizin özelliğine uygulandığında Array, seyrek olarak doldurulmuş bir dizi (yani dizini eksik olan bir dizi) oluşturacağınızı unutmayın.

Örneklerle çalışırken, Arrayseyrek nüfuslu bir dizi oluşturmak istemiyorsanız - ve genellikle yapmıyorsanız - Array#spliceveya kullanmalısınız Array#pop.

Not deleteJavaScript operatör boş bellek doğrudan değil. Amacı, nesnelerden özellikleri kaldırmaktır. Elbette, silinmekte olan bir özellik bir nesneye kalan tek referansı tutarsa o, daha sonra onormal şekilde çöp toplanır.

İşlecin kullanılması deleteJavaScript motorlarının kodu optimize etme yeteneğini etkileyebilir .


18
Bu, bir Array nesnesi örneğinde varolan bir öğeyi kaldırmak için kullanıldığında sorunlara neden olur, örn delete myArray[0]. Bkz. Stackoverflow.com/a/9973592/426379 ve Dizi öğelerini silme
Saul

4
Hangi problemlere neden olacak?
Nisan'da Gottox

26
@Gottox - lengthBir Array nesnesinin özelliği değişmeden kalır.
Saul

12
@Saul: Gerçekten bir dizi olarak kullanılmış olsaydı sorunlar olurdumyArray - ama değil ( myArraytalihsiz bir isim), bir nesnedir. Yani bu durumda deletesorun yok. new Array()İlişkilendirilebilir dizi olarak oluşturulmuş ve kullanılmış olsa bile yine de iyi olacağını unutmayın. Uyarınız hala gerçek diziler kullanıp kullanmadığının farkında olmak için bir şey.
johndodo

2
@johndodo - Doğru. Ben ile benim ilk yorumunu başladı nedeni budur sorunlara neden olur Bu ise bir kullanılan Array nesnesi örneği . Yine de her durumda doğru şekilde çalışan bir yaklaşımı tercih ederim, aşağıdaki cevabımı görün.
Saul

79

JavaScript'teki tüm nesneler karma / ilişkilendirilebilir diziler olarak uygulanır. Yani, aşağıdakiler eşdeğerdir:

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

Ve daha önce de belirtildiği gibi, bir özelliği deleteanahtar kelimeyle iki yolla kullanabileceğiniz bir nesneyi "kaldırırsınız" :

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

Ekstra bilgi yardımcı olur umarım ...


10
özellik basit bir terim değilse nokta gösteriminin çalışmadığına dikkat edilmelidir. yani myObj['some;property']çalışır, ancak myObj.some;propertyolmaz (bariz nedenlerle). Ayrıca, parantez gösteriminde bir değişken kullanabileceğiniz açık olmayabilir, yanivar x = 'SomeProperty'; alert(myObj[x])
Kip

2
"JavaScript'teki tüm nesneler karma / ilişkilendirilebilir diziler olarak uygulanır." - yanlış. V8, bir nesneyi gizli sınıf + yoğun paketlenmiş alanlar olarak depolamayı tercih eder. Sadece onlara garip şeyler yaparsanız (alanları kaldırmak gibi) vazgeçer ve sahnelerin arkasında bir karma harita kullanır.
John Dvorak

4
@JanDvorak - hey, bu cevabın ilk ne zaman yazıldığını biliyorsun, değil mi? Bu açıklama çoğu amaç için hala yeterliydi. Bununla birlikte, bıktırıcı derecede bilgiç olduğumu anlıyorum. :)
Jason Bunting

41

Önceki yanıtların hiçbiri, Javascript'in başlangıçta ilişkilendirilebilir dizileri olmadığı gerçeğini ele almaz - arrayböyle bir tür yoktur , bkz typeof.

Javascript'in sahip olduğu, dinamik özelliklere sahip nesne örnekleridir. Özellikler bir Array nesnesi örneğinin öğeleriyle karıştırıldığında, Bad Things ™ gerçekleşir:

Sorun

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

Çözüm

Sizi havaya uçurmayan evrensel bir kaldırma işlevine sahip olmak için şunu kullanın:

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
Bu çözümün iki sorunu vardır: dizilerin ve nesnelerin JS'de tamamen farklı canavarlar olduğu gerçeğini gizler (biliyorsunuz, ama görünüşe göre OP bilmiyor) ve prototipleri kullanıyor. OP, diziler ve nesneler hakkında bilgi sahibi olsaydı daha iyi olurdu (ve değişkenlerini buna göre adlandırırdı) - ikisi arasındaki farkları gizlemeye çalışmak onu sadece daha fazla belaya sokar. Tabii ki IMHO.
johndodo

1
@johndodo - tüm ArrayJS ler nesneler, denemek vardır typeof new Array();ya typeof []doğrulamak için. Arraybasitçe belli bir tür nesnedir ve hiç de "farklı bir canavar" değildir. JS'de, nesneler yapıcı adlarına ve prototip zincirlerine göre ayrılır; bkz. Prototip tabanlı programlama .
Saul

9
Konuyu kaçırıyorsun. Dizilerin de nesne olduğunu biliyorum, ama bu onları bu şekilde kullanmanın akıllıca olduğu anlamına gelmez. Programcı dizi (push, pop, [], ...) veya nesne / "ilişkisel dizi" olarak kullanmak isteyip istemediğine karar vermelidir. Karıştır ve eşleştir, tam olarak çözümünüzün gizlemeye çalıştığı sorunlar nedeniyle iyi bir tarif değil. Hangi tasarım deseninin (dizi veya nesne) kullanılacağına önceden karar verirseniz, böyle bir sorun olmaz.
johndodo

7
@johndodo - Özellikle hangi sorunlardan bahsediyorsunuz? Yukarıdaki kodun amacı, deleteoperatörün Arraybasit bir polimorfik fonksiyon sağlayarak sahip olduğu eksikliğin giderilmesidir .
Saul

1
deleteeksikliği yoktur. deleteözellikleri kaldırmak için tasarlanmıştır. Bu kadar. Delete operatörünün bir dizinin dizinine uygulanması o dizini kaldırır. Daha ne gerek? Dilin bir özelliği olan seyrek bir dizi ile kalırsınız. Seyrek bir dizi istemiyorsanız, dizini silmeyin: use spliceor pop.
Ben Aston

35

Bu yalnızca kaldırılan nesneyi siler ancak dizi uzunluğunu aynı tutar.

Kaldırmak için aşağıdaki gibi bir şey yapmanız gerekir:

array.splice(index, 1);

11
Gerçekten de, ancak bu durumda bir dizi kullanılmıyor, sadece düz eski bir nesne, bu nedenle uzunluk veya ekleme yöntemi yok.
MooGoo

2
@Andreaa Panagiotidis Diziler hakkında konuşmadığımız durumlar dışında, bu durumda zamanın% 100'ü yanlıştır 🙂
Drenai

17

Kabul edilen cevap doğru olmakla birlikte, neden çalıştığına dair açıklama eksiktir.

Her şeyden önce, kodunuz bunun bir dizi DEĞİLDİR gerçeğini yansıtmalıdır :

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

Tüm nesnelerin (s'ler dahil Array) bu şekilde kullanılabileceğini unutmayın. Ancak, standart JS dizi işlevlerinin (pop, push, ...) nesneler üzerinde çalışmasını beklemeyin!

Kabul edilen cevapta belirtildiği gibi, deletegirişleri nesnelerden kaldırmak için kullanabilirsiniz :

delete myObject["lastname"]

Hangi rotayı kullanmak istediğinize karar vermelisiniz - nesneleri (ilişkilendirilebilir diziler / sözlükler) veya dizileri (haritalar) kullanın. Asla ikisini karıştırmayın.


6
Çok iyi bir cevap. Sadece bunu okuyan herkese javascript dizileri 'haritalar' olarak değil, 'listeler' olarak soyutlanması gerektiğini tavsiye ederim. Bunun nedeni, dizileri kullanırken öğelerin dizini üzerinde kontrol sahibi olmamanız gerektiğidir. Bunu denerseniz ... iyi, sadece yapmayın: D
rodolfo42 4:14

6

spliceBir nesne dizisinden öğeyi tamamen kaldırmak için yöntemi kullanın :

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
Bu daha genel bir çözümdür, js dosyanıza eklenebilir ve yöntem sadece bir dizi için değil, tüm diziler için kullanılabilir olacaktır.
Hussain

6

Diğer yanıtların belirttiği gibi, kullandığınız şey bir Javascript dizisi değil, tüm anahtarların dizelere dönüştürülmesi dışında neredeyse diğer dillerde ilişkilendirilebilir bir dizi gibi çalışan bir Javascript nesnesidir. Yeni Harita , anahtarları orijinal türleri olarak saklar.

Nesneniz değil diziniz varsa, kaldırılmasını istediğiniz öğe olmadan yeni bir dizi döndürmek için dizinin .filter işlevini kullanabilirsiniz :

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

Daha eski bir tarayıcınız ve jQuery'niz varsa, jQuery'nin benzer şekilde çalışan bir $.grepyöntemi vardır:

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

mükemmel bir açıklama. İstenen sonucu elde etmek için filtre kullandım. Dönüş öğesinin nesneyi diziden kaldırmak için nasıl çalıştığını açıklar mısınız? Sürece dahil dize içermiyorsa dizi döndürdüğünü varsayıyorum.
Edward


5

Object kullanıyorsunuz, başlamak için ilişkilendirilebilir bir diziniz yok. İlişkilendirilebilir bir dizi ile öğe eklemek ve kaldırmak şu şekilde olur:

    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

Haritanızdan bir girişi açıkça 'tanımsız' olarak atayarak kaldırabilirsiniz. Sizin durumunuzda olduğu gibi:

myArray ["lastname"] = tanımsız;


Bu, anahtarın sözlükte var olup olmadığından emin olmadığı, ancak olması durumunda sterilize etmek istediği durumlarda yararlı olabilir. Yanılıyorsam düzelt beni Amytis.
Hassan Baig

3

Herhangi bir nedenle silme tuşu çalışmıyorsa (benim için çalışmıyormuş gibi)

Ekleyebilir ve tanımsız değerleri filtreleyebilirsiniz

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

Ekleme kaldırılan öğeleri döndürdüğü için bunları denemeyin ve zincirlemeyin;


3

Bunu bir işlev olarak da kullanabiliriz. Prototip olarak kullanıldığında açısal bazı hatalar verir. Teşekkürler @HarpyWar. Bir problemi çözmeme yardımcı oldu.

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"Anahtar kelimeyi kullanarak, dizi öğesini javascript içindeki diziden siler.

Örneğin,

Aşağıdaki ifadeleri düşünün.

var arrayElementToDelete = new Object();

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

delete arrayElementToDelete["status"];

Kodun son satırı, anahtarı "status" olan dizi öğesini diziden kaldırır.


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

Döngü / yineleme olmadan aynı sonucu alırız


0

"Diziler" için:

Dizini biliyorsanız:

array.splice(index, 1);

Değeri biliyorsanız:

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

En çok oylanan cevap delete, nesneler için iyi çalışır, ancak gerçek diziler için değil. I kullanma durumunda deletebu döngüler elemanı çıkarır ama eleman tutar emptyve dizi alışkanlık değişim uzunluğu. Bu, bazı senaryolarda bir sorun olabilir.

Örneğin, üzerinden kaldırdıktan sonra myArray üzerinde myArray.toString () yöntemini yaparsam delete, boş bir giriş oluşturur yani,


0

Benim için tek çalışma yöntemi:

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

kullanımı:

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

Bunun yerine neden filtre kullanmıyorsunuz? Bu filtre için mükemmel bir kullanım durumudur
Code Maniac
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.