JavaScript'te bir Set oluşturmanın yolları?


83

Eloquent JavaScript, Bölüm 4'te, bir nesne oluşturarak ve değerleri özellik adları olarak depolayarak, rastgele değerler (örneğin, doğru) özellik değerleri olarak atayarak bir değerler kümesi oluşturulur. Değerin kümede zaten bulunup bulunmadığını kontrol etmek için inoperatör kullanılır:

var set = {};

if (!'Tom' in set) { 
  set.Tom = true;
}

Bu deyimsel JavaScript mi? Bir dizi daha iyi kullanılmaz mı?

var set = [];

if (!'Tom' in set) { 
  set.push = 'Tom';
}

1
Nasıl 'Tom' in setgörünmesi doğru olan bir diziyi beklersiniz ? Bu konuda yanlış varsayımları var çok benziyor şey , ve dışarı bulmaya çalışıyorum ne hakkında .

10
Bilginize, sen parens gerekir: if(!('Tom' in set)). Şu anda o false in setzamandan beri demek !'Tom' === false.
pimvdb

ES6'nın setleri var, aşağıdaki John'un cevabına bakın
Ben Taliadoros

Yanıtlar:


101

Setler artık ES2015'te (ES6, yani ECMAScript 6) mevcuttur. ES6, Haziran 2015'ten beri JavaScript için geçerli standarttır.

ECMAScript 6, rasgele değerler için çalışan, hızlı ve NaN'yi doğru şekilde işleyen veri yapısı Setine sahiptir. - Axel Rauschmayer , ES6'yı Keşfetmek

Axel Rauschmayer'in ES6'yı Keşfetmek kitabından ilk iki örnek :

Tek öğelerin yönetilmesi:

> let set = new Set();
> set.add('red')

> set.has('red')
true
> set.delete('red')
true
> set.has('red')
false

Bir Setin boyutunu belirleme ve onu temizleme:

> let set = new Set();
> set.add('red')
> set.add('green')

> set.size
2
> set.clear();
> set.size
0

Ben kontrol ederim ES6 keşfetmek JavaScript'te Kümeleri hakkında daha fazla bilgi edinmek istiyorsanız. Kitabı çevrimiçi olarak okumak ücretsizdir, ancak yazar Dr. Axel Rauschmayer'i desteklemek isterseniz kitabı yaklaşık 30 dolara satın alabilirsiniz.

Setleri ve ES6'yı kullanmak istiyorsanız şimdi Babel , ES6'dan ES5'e aktarıcıyı ve çoklu dolgularını kullanabilirsiniz .

Düzenleme: 6 Haziran 2017 itibarıyla başlıca tarayıcıların çoğu, en son sürümlerinde tam Set desteğine sahiptir (IE 11 hariç). Bu, eski tarayıcıları desteklemeyi umursamıyorsanız babel'e ihtiyacınız olmayabileceği anlamına gelir. Mevcut tarayıcınız da dahil olmak üzere farklı tarayıcılarda uyumluluğu görmek istiyorsanız, Kangax'ın ES6 uyumluluk tablosuna bakın .

DÜZENLE:

Sadece başlatma hakkında açıklama. Kümeler, yapıcılarında herhangi bir eşzamanlı yinelemeli olabilir. Bu, sadece dizileri değil aynı zamanda dizeleri ve yineleyicileri de alabilecekleri anlamına gelir. Örneğin, bir kümenin aşağıdaki dizi ve dize ilklendirmesini ele alalım:

const set1 = new Set(['a','a','b','b','c','c']);
console.log(...set1);
console.log(set1.size);
const set2 = new Set("aabbcc");
console.log(...set2);
console.log(set2.size);

Dizinin ve dizenin her iki çıkışı da aynıdır. Bunun yayılma sözdizimi olduğuna dikkat ...set1edin . Yinelenebilir öğenin her bir öğesi tek tek kümeye eklendiği için, hem dizi hem de dize aynı öğelere sahip olduğundan ve öğeler aynı sırada olduğundan set aynı şekilde oluşturulur. Kümeler hakkında dikkat edilmesi gereken bir diğer nokta, üzerlerinde yineleme yaparken, yineleme sırası, öğelerin kümeye eklenme sırasını izler. Bir küme üzerinde yineleme örneği:

const set1 = new Set(['a','a','b','b','c','c']);
for(const element of set1) {
  console.log(element);
}

Bir kümeyi başlatmak için herhangi bir yinelenebilir kullanabildiğiniz için, bir üreteç işlevinden bir yineleyici bile kullanabilirsiniz . İşte aynı çıktıyı üreten bu tür yineleyici başlatmalarının iki örneği:

// a simple generator example
function* getLetters1 () {
  yield 'a';
  yield 'a';
  yield 'b';
  yield 'b';
  yield 'c';
  yield 'c';
}

// a somewhat more commonplace generator example
// with the same output as getLetters1.
function* getLetters2 (letters, repeatTimes) {
  for(const letter of letters) {
    for(let i = 0; i < repeatTimes; ++i) { 
      yield letter;
    }
  }
}

console.log("------ getLetters1 ------");
console.log(...getLetters1());
const set3 = new Set(getLetters1());
console.log(...set3);
console.log(set3.size);

console.log("------ getLetters2 ------");
console.log(...getLetters2('abc', 2));
const set4 = new Set(getLetters2('abc', 2));
console.log(...set4);
console.log(set4.size);

Bu örneklerin oluşturucu işlevleri, tekrar edilmeyecek şekilde yazılabilir, ancak jeneratör işlevi daha karmaşıksa ve aşağıdakiler performansı çok olumsuz etkilemediği sürece Tekrar etmeyin.

Dr. Rauschmayer'in kitabının bölümünü okumadan setler hakkında daha fazla bilgi edinmek isterseniz Set'teki MDN belgelerine göz atabilirsiniz . MDN da kullanmak gibi bir dizi yinelemek daha fazla örnek vardır forEachkullanarak .keys, .valuesve .entriesyöntemler. MDN'de ayrıca set birleşimi, set kesişimi, set farkı, simetrik set farkı ve set süperset kontrolü gibi örnekler vardır. Umarım bu işlemlerin çoğu, onları destekleyen kendi işlevlerinizi oluşturmanıza gerek kalmadan JavaScript'te kullanılabilir hale gelir. Aslında, teklif 4. aşamaya ulaşırsa ileride bir zamanda JavaScript'te Ayarlamak için aşağıdaki yöntemleri eklemesi gereken yeni Set yöntemleri için bu TC39 önerisi vardır :

  • Set.prototype.intersection (yinelenebilir) - yöntem, set kesişim işlemiyle yeni Set örneği oluşturur.
  • Set.prototype.union (yinelenebilir) - yöntem, set birleşim işlemiyle yeni Set örneği oluşturur.
  • Set.prototype.difference (yinelenebilir) - yöntem, yinelenebilir durumda bulunan öğeler olmadan yeni Set oluşturur.
  • Set.prototype.symmetricDifference (yinelenebilir) - yalnızca bu veya yinelenebilir durumda bulunan öğeler kümesini döndürür.
  • Set.prototype.isSubsetOf (yinelenebilir)
  • Set.prototype.isDisjointFrom (yinelenebilir)
  • Set.prototype.isSupersetOf (yinelenebilir)

Ayrıca Kümenin kendileri yinelenebilir, böylece bir kopya oluşturmak için kümeleri diğer kümelerle başlatabilir veya bir birleşim işlemi için yeni Küme ([... setA, ... setB]) gibi bir şey yapabilirsiniz.
John

1
@LanceKind Sadece dizilerle değil, yinelenebilir herhangi bir diziyle de kümeleri başlatabileceğinizi gösteren bazı ek bilgiler ekledim.
John

32

Dikte nesneleri setler olarak kullanıyorum. Bu, dizeler ve sayılarla çalışır, ancak özel eşitlik ve karşılaştırma işleçlerini kullanarak bir dizi nesneye sahip olmak istiyorsanız sorunlara neden olacağını düşünüyorum:

Bir set oluşturmak:

var example_set = 
{
    'a':true,
    'b':true,
    'c':true
}

Bir sete dahil edilmeyi test etme

if( example_set['a'] ){
    alert('"a" is in set');
}

Bir kümeye bir eleman eklemek

example_set['d'] = true;

Bir kümeden bir öğeyi çıkarma

delete example_set['a'];


1
Üzerinde çalıştığım kod, motorun desteği olmayan eski bir sürümünü kullanıyordu Set. Bu yardımcı oldu.
Abhijith Madhav

16

Kümeler, yinelenen girişlere izin vermez ve genellikle önceden tanımlanmış sıralamayı garanti etmez. Diziler bunların her ikisini de yapar, böylece küme olmanın ne anlama geldiğini ihlal eder (ek kontroller yapmadığınız sürece).


2
Dizi, yinelenen girişleri filtrelemez ... örneğin, Objective-C'deki
NSSet

Eğer onu mot-a-mot olarak kabul edersen, hayır. Ancak id'yi dizi (harita) anahtarı olarak kullanabilirsiniz. arr[id] = {"name": "Jake"};
Buffalo

11

İlk yol, deyimsel JavaScript'tir.

Bir anahtar / değer çifti depolamak istediğinizde, bir JavaScript nesnesi kullanmanız gerekir. Dizilere gelince, birkaç sorun var:

  1. İndeks sayısal bir değerdir.

  2. Döngü olmadan bir değerin bir dizide olup olmadığını kontrol etmenin kolay bir yolu yok.

  3. Bir küme, kopyalara izin vermez. Bir dizi yapar.


Mülk değerine atamak en iyi ne olabilir?
helpermethod

1
Yinelenen öğeleri JavaScript dizilerinden kaldırmak mümkündür. stackoverflow.com/a/12166248/975097
Anderson Green

9

Bir diziden bir küme oluşturmak istiyorsanız, yapmanız gereken:

let arr = [1, 1, 2, 1, 3];
let mySet = new Set(arr); // Set { 1, 2, 3 }

Bu, Python'da programlama yaparken çok sevdiğim bir şeker sözdizimi, ES6'nın sonunda aynı şeyi yapmayı mümkün kıldığına çok sevindim.

NOT: O zaman söylediklerimin sorunuzu doğrudan cevaplamadığını anladım. ES5'te bu "hack" e sahip olmanızın nedeni, bir nesnede anahtarlara göre arama süresinin bir diziden (O (n)) önemli ölçüde daha hızlı (O (1)) olmasıdır. Performans açısından kritik uygulamalarda, daha iyi performans için bu biraz okunabilirlikten veya sezgiden ödün verebilirsiniz.

Ama hey, şimdi tüm büyük modern tarayıcılarda uygun Set'i kullanabileceğiniz 2017'ye hoş geldiniz !


6

İçinde Setleri ES6/ ' ES2015:

ES6/ ES2015şimdi setler oluşturdu. Küme, ister ilkel değerler ister nesne referansları olsun, her türden benzersiz değerlerin depolanmasına izin veren veri yapısıdır. Bir küme, ES6yerleşik küme yapıcısı kullanılarak aşağıdaki şekilde bildirilebilir:

const set = new Set([1, 2, 3, 4, 5]);

Set yapıcısını kullanarak bir set oluştururken, yeni oluşturulan set nesnemiz Set.prototype. Bunun her türlü yardımcı yöntemi ve özelliği vardır. Bu, aşağıdaki şeyleri kolayca yapmanızı sağlar:

Misal:

const set = new Set([1, 2, 3, 4, 5]);

// checkout the size of the set
console.log('size is: ' + set.size);

// has method returns a boolean, true if the item is in the set
console.log(set.has(1));

// add a number
set.add(6);

// delete a number
set.delete(1);

// iterate over each element using a callback
set.forEach((el) => {
  console.log(el);
});

// remove all the entries from the set
set.clear();

Tarayıcı Uyumluluğu:

Bazı özelliklerin eksik olduğu IE dışındaki tüm büyük tarayıcılar artık setleri tam olarak desteklemektedir. Tam referans için lütfen mdn belgelerine bakın .


@Velojet: Tamam, yeterince adil.
kjhughes

3

Kümeleri taklit etmek için çıplak javascript nesnelerini kullanmanın iki problemi vardır: birincisi, bir nesne "in" operatörünü vidalayacak miras alınmış bir özelliğe sahip olabilir ve ikincisi, yalnızca bu şekilde skaler değerleri saklayabilirsiniz, bir dizi nesnenin yapılmaması mümkün. Bu nedenle, Setleri gerçekçi uygulama yöntemleri vermelidir addve containsyerine düz bir inve mülkiyet atamaları.


@kojiro: nesneler anahtar olarak kullanıldıklarında dizelere dönüştürülür:set={};set[{x:1}]=123;alert(set[{z:99}])
georg

3

Buckets deneyebilirsiniz , bir javascript veri yapısı kitaplığıdır ve kümeleri işlemek için ihtiyacınız olan her şeye sahiptir.


addAll (dizi) yöntemi sağlıyor mu?
jorrebor

1

Set nesnesinin temel oluşturulması ve kullanımı 🔷

let mySet = new Set()

mySet.add(2)         // Set {2}
mySet.add(7)         // Set {2, 7}
mySet.add(7)         // Set {2, 7}
mySet.add('my text') // Set {2, 7, 'my text'}
let myObj = { a: 1, b: 2 }
mySet.add(myObj)     // Set {2, 7, 'my text', {...}}
mySet.has(2)         // true
mySet.has(myObj)     // true
mySet.size           // 4

Yineleme

for (let item of mySet) console.log(item)  // 2, 7, 'my text', {a:1, b:2}
mySet.forEach(value => console.log(value)) // 2, 7, 'my text', {a:1, b:2}

Diziye dönüştür

var myArr = Array.from(mySet)             // [2, 7, 'my text', {a:1, b:2}]

❕ Set'in sunduğu en belirgin özellik, Set nesnesindeki her değerin benzersiz olması gerektiğidir. Yani yinelenen değerler ekleyemezsiniz.

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.