TypeCript Haritası Üzerinde Yineleme


135

Bir daktilo haritası üzerinde yinelemeye çalışıyorum, ancak hata almaya devam ediyorum ve bu kadar önemsiz bir soruna henüz bir çözüm bulamadım.

Benim kodum:

myMap : Map<string, boolean>;
for(let key of myMap.keys()) {
   console.log(key);
}

Ve Hatayı alıyorum:

'IterableIteratorShim <[string, boolean]> yazın' bir dizi türü veya bir dize türü değil.

Tam Yığın İzleme:

 Error: Typescript found the following errors:
  /home/project/tmp/broccoli_type_script_compiler-input_base_path-q4GtzHgb.tmp/0/src/app/project/project-data.service.ts (21, 20): Type 'IterableIteratorShim<[string, boolean]>' is not an array type or a string type.
    at BroccoliTypeScriptCompiler._doIncrementalBuild (/home/project/node_modules/angular-cli/lib/broccoli/broccoli-typescript.js:115:19)
    at BroccoliTypeScriptCompiler.build (/home/project/node_modules/angular-cli/lib/broccoli/broccoli-typescript.js:43:10)
    at /home/project/node_modules/broccoli-caching-writer/index.js:152:21
    at lib$rsvp$$internal$$tryCatch (/home/project/node_modules/rsvp/dist/rsvp.js:1036:16)
    at lib$rsvp$$internal$$invokeCallback (/home/project/node_modules/rsvp/dist/rsvp.js:1048:17)
    at lib$rsvp$$internal$$publish (/home/project/node_modules/rsvp/dist/rsvp.js:1019:11)
    at lib$rsvp$asap$$flush (/home/project/node_modules/rsvp/dist/rsvp.js:1198:9)
    at _combinedTickCallback (internal/process/next_tick.js:67:7)
    at process._tickCallback (internal/process/next_tick.js:98:9)

Angular-cli beta5 ve typcript 1.8.10 kullanıyorum ve hedefim es5. Bu sorunu olan var mı?


Yanıtlar:


214

Onun Map.prototype.forEach((value, key, map) => void, thisArg?) : voidyerine kullanabilirsin

Bunu şu şekilde kullanın:

myMap.forEach((value: boolean, key: string) => {
    console.log(key, value);
});

15
Sadece bununla karşılaştım. TypeScript, en azından bir for-of döngüsü belirten MDN'ye göre, harita yinelemesine yönelik spesifikasyona uyuyor gibi görünmüyor . .forEach
kıramayacağınız için optimalin altında

14
bilmiyorum neden değeri sonra anahtar. Geriye doğru görünüyor.
Paul Rooney

@PaulRooney muhtemelen uyum sağlamak için böyle Array.prototype.map.
Ahmed Fasih

1
İhtiyacımız olanı bulursak bu yineleme sürecini nasıl durdurabiliriz?
JavaRunner

36

ES6

for (let [key, value] of map) {
    console.log(key, value);
}

ES5

for (let entry of Array.from(map.entries())) {
    let key = entry[0];
    let value = entry[1];
}

1
Yukarıda verilen es6 sürümü katı modda derlenmemektedir.
Stephane

Teşekkür ederim, efendim.
Kitanga Nday

36

Bunu Array.from()şuna dönüştürmek için yöntemi kullanın Array:

myMap : Map<string, boolean>;
for(let key of Array.from( myMap.keys()) ) {
   console.log(key);
}

5
Haritaları dönüştürmek, çok performans gerektiren bir işlemdir ve esasen yalnızca derleyicinin dilin temel bölümlerini gizlediği bir sorunu çözmenin doğru yolu değildir. Sadece <any>-of-of ile yinelemek için haritayı yayınlayın.
Kilves

1
Dikkat: Yukarıdaki @Kilves'in Harita'yı "herhangi biri" olarak yayınlama önerisinin zarif bir çözüm olduğunu düşündüm. Bunu yaptığımda, kod derlendi ve şikayet edilmeden çalıştı, ancak Harita aslında yinelenmedi - döngünün içeriği hiçbir zaman yürütülmedi. Array.from()Strateji Burada önerilen benim için çalışma yaptı.
mactyr

Bunu da denedim, benim için de işe yaramadı, bu ES6'nın bir parçası olduğu ve çoğu tarayıcıda "sadece çalışması" gerektiği düşünüldüğünde daha da aptalca. Ama sanırım açısal efendilerimiz zone.js'de çalışmamasını sağlamak için sihirli bir mumbo jumbo kullanıyor, çünkü ES6'dan nefret ediyorlar. İç çekmek.
Kilves

28

Kullanılması Array.from , Array.prototype.forEach () ve işlevleri ok :

Anahtarları yineleyin :

Array.from(myMap.keys()).forEach(key => console.log(key));

Değerleri yineleyin :

Array.from(myMap.values()).forEach(value => console.log(value));

Girişleri yineleyin :

Array.from(myMap.entries()).forEach(entry => console.log('Key: ' + entry[0] + ' Value: ' + entry[1]));

2
Neden emin değilim, Map <String, CustomeClass> gibi bir haritam var. Array.from (myMap.values ​​()). forEach (value => console.log (value)); dışında yukarıdaki yöntemlerden hiçbiri çalışmadı.
Rajashree Gr

27

Bu benim için çalıştı. TypeScript Sürümü: 2.8.3

for (const [key, value] of Object.entries(myMap)) { 
    console.log(key, value);
}

7
Bunu, Object.entries (myMap) 'ı sadece myMap.entries () olarak değiştirerek çalıştırdım. Bu yanıtı beğendim çünkü .forEach çağrılarının hata işleme tuzaklarından kaçınıyor.
2018

2
Senin eğer dikkati çekiyor targetiçinde tsconfigolduğunu es5fakat bu bir hata atar es6eserlerin doğru. Ayrıca, sadece yapabilirsiniz for (const [key, value] of myMap)hedeflerkenes6
Benjamin Vogler

16

Başına "Yeni daktilo harfleri 2.3 sürüm notları --downlevelIteration" :

for..of statements, Array, Call ve New ifadelerindeki Array Destructuring ve Spread öğeleri, kullanılırken varsa ES5 / E3'te Symbol.iterator'ı destekler --downlevelIteration

Bu, varsayılan olarak etkin değildir! Ekle "downlevelIteration": trueBlogunuza tsconfig.jsonveya pas --downlevelIterationbayrağını tsctam yineleyici destek almak için.

Bu yerindeyken, yazabilirsiniz for (let keyval of myMap) {...}ve keyvaltürüne otomatik olarak ulaşılır.


Bu neden varsayılan olarak kapalıdır? TypeScript katılımcısı @ aluanhaddad'a göre ,

İsteğe bağlıdır, çünkü yinelenenlerin tüm kullanımları için (diziler dahil) üretilen kodun boyutu ve potansiyel olarak performans üzerinde çok önemli bir etkiye sahiptir.

ES2015'i ( "target": "es2015"içinde tsconfig.jsonveya tsc --target ES2015daha sonra) hedefleyebiliyorsanız , etkinleştirmek downlevelIterationakıllıca değildir, ancak ES5 / ES3'ü hedefliyorsanız, yineleyici desteğinin performansı etkilememesini sağlamak için kıyaslama yapabilirsiniz (eğer öyleyse, daha iyi olabilirsiniz) kapalı Array.fromdönüştürme veya forEachbaşka bir geçici çözüm ile).


Angular'ı kullanırken bunu etkinleştirmek uygun mu yoksa tehlikeli mi?
Simon_Weaver

9

Bu benim için çalıştı.

Object.keys(myMap).map( key => {
    console.log("key: " + key);
    console.log("value: " + myMap[key]);
});

2
Bununla birlikte, anahtarlar her zaman dizge olacaktır
Ixx

8

En son TS ve düğümü kullanıyorum (sırasıyla v2.6 ve v8.9) ve şunları yapabilirim:

let myMap = new Map<string, boolean>();
myMap.set("a", true);
for (let [k, v] of myMap) {
    console.log(k + "=" + v);
}

Eğer ilk sete sahip olduğunu teyit edebilir "downlevelIteration": trueGözlerinde farklı tsconfig.json?
Ahmed Fasih

3
Bende olmayan downlevelIteratonset, benim hedeftir es2017ancak.
lazieburd

Bunu Map <string, CustomClass []> öğesi için yapamaz mıyım? derleyici, bunun bir tür veya dize türü dizisi olmadığını söylüyor.
Rajashree Gr

bu benim için çalışmıyor 2.8 - AnlıyorumType 'Map<K, V>' is not an array type or a string type.
Simon_Weaver

3

Dizi eşleme yöntemini Map.entries () yinelenebilir öğesine de uygulayabilirsiniz:

[...myMap.entries()].map(
     ([key, value]: [string, number]) => console.log(key, value)
);

Ayrıca, diğer yanıtlarda belirtildiği gibi, tsconfig.json dosyanızda alt düzey yinelemeyi etkinleştirmeniz gerekebilir (derleyici seçenekleri altında):

  "downlevelIteration": true,

Bu özellik TypeScript 2.3'te tanıtıldı. Sorun TypeScript 1.8.10 ile oluştu
mwe

"DownlevelIteration" kullanamıyorsanız, şunları kullanabilirsiniz:const projected = Array.from(myMap).map(...);
Efrain

1

Bir HTML belgesinde kullanmak için basit bir açıklama.

Bir tür eşlemeniz (anahtar, dizi) varsa, diziyi şu şekilde başlatırsınız:

public cityShop: Map<string, Shop[]> = new Map();

Ve üzerinde yinelemek için, anahtar değerlerden bir dizi oluşturursunuz.

Sadece aşağıdaki gibi bir dizi olarak kullanın:

keys = Array.from(this.cityShop.keys());

Ardından, HTML'de şunları kullanabilirsiniz:

*ngFor="let key of keys"

Bu döngünün içinde, sadece dizi değerini alırsınız:

this.cityShop.get(key)

Bitti!


1

Typescript 3.5 ve Angular 8 LTS üzerinde, aşağıdaki gibi tür çevirmek gerekiyordu:

for (let [k, v] of Object.entries(someMap)) {
    console.log(k, v)
}

-1

İç içe geçmiş işlevleri gerçekten sevmiyorsanız, tuşlar üzerinde de yineleme yapabilirsiniz:

myMap : Map<string, boolean>;
for(let key of myMap) {
   if (myMap.hasOwnProperty(key)) {
       console.log(JSON.stringify({key: key, value: myMap[key]}));
   }
}

Unutmayın, anahtar olmayan yinelemeleri filtrelemeniz gerekir hasOwnProperty, bunu yapmazsanız bir uyarı veya hata alırsınız.


html'de harita üzerinde nasıl yineleme yapılır? hiç işe yaramıyor gibi görünüyor. <div ng-tekrar = "(anahtar, değer) model.myMap içinde"> {{anahtar}}. </div>
Shinya Koizumi

@ powerfade917 Çalışmıyor, sadece diziler için çalışıyor çünkü açısal bir çöp yığınıdır. Ama bunu yeni bir soru olarak sorun ve böylece öğreneceksiniz ki, açısal bir çöp yığını değildir, ama onu bir diziye dönüştürmelisiniz. Ayrıca, programlamanın zirvesinde değilsiniz, çünkü görünüşte açısal ve daktilo arasında ayrım yapmakta yetersizsiniz.
peterh - Monica'yı eski durumuna getir
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.