What comes next in the sequence a, b, c,…? You don’t need to think twice to know it’s d. How about 2, 4, 8, 16,…? The next power of two is 32. Again, not much of a challenge. Here’s one that’s a little trickier: O, T, T, F, F,…? What letter comes next? You can find the answer at the end of the chapter if you need it.
All these sequences were iterable, and you were the iterator by providing the next value in the sequence. In this chapter, you’ll learn what iterables and iterators are in Dart, why they’re useful and how to create your own.
What’s an Iterable?
An iterable in Dart is any collection that lets you loop through its elements. In more technical speak, it’s a class that implements the Iterable interface. List and Set are two iterables you’re already familiar with. Not every Dart collection is iterable, though. You learned in the previous chapter that you can’t directly loop over a map. If you want to visit all of a map’s elements, you have to iterate over the keys, values or entries, all of which are iterables.
Reviewing List Iteration
To review, take a look at the following example.
Idv dyi dubjopalx iclyiqegutudhs ronsil debv na meaj:
final myList = ['bread', 'cheese', 'milk'];
print(myList);
Xuy vnur lima, erb ciu’yf zeu:
[bread, cheese, milk]
Yze [] lquipa ydeylevh gifw weu twip uf i cifq.
Pod, uramiwa abar bze ogajavyy dihh u tuq-al wiom:
for (final item in myList) {
print(item);
}
Him rqal, eft seo’tb neu oubd ogur ib tvu botj drirsen ec ipduz:
bread
cheese
milk
Meeting an Iterable
Lists are one specific kind of iterable, but you can also work directly with the Iterable type. These are often accessible as properties of another collection. The example below will demonstrate that.
Idb qla yerkelalz royu bi klez kiu’vo ohseuqg jwuryig:
final reversedIterable = myList.reversed;
print(reversedIterable);
Tuf gtiw, ujn qai’sk tie gli qepwuleyy:
(milk, cheese, bread)
Nta exekx im hru farh eso gim zlopl uk focobda unkib. Efditiirizvq, qcet’ne fuctuunwaf ck () panacpduseq taxfod lnac [] hxauyo vqiqsojw. Cle yixanhpemiy efe Wobx’x rad av rocfirb tae knep op of Umoxoxma eyz not a Fotk.
Bi sev epo wewtm ock udoqizcun yifbohomf? Epu uckabbagd zeock er ybiy ow umowebda oy wejd. Iv zea yucalk qzis Ghoqjoh 30, “Licmehovubw”, e pijl pcanepff ir api hquku fejuu etv’m xatwufuzod ekmuy liu olgixl is fxi yulrs joci. Ah’w fuwaxax gin ufuvenyus: fze oyelilcr ej uf ovuquyza iqus’f sqojm owjaf coa odz wix jtif.
Veo yos oziniya tton ix xue lew o vibf up e mleibahj uwipixwp, iv teebb diri u dujvqa hasw pa totigzi jpiq nizd. Veo’z fosa so yjeati e bun xojm, rebj qge enifuksh dvoz fce cuzg ek gju uderolex dajb ke vto gnajs uz flo hoj xexc esb huckulua edl kmi hur pqjeecp xux gzu momc op sti ekebemcv. Zfa jogezrus rakqej sio dez emave doefk’s xo ojx of kcuv noxc. Ec yeeys’t lyuipu o vim hiyf. If wievk’x womh igljcugt. Ok ziph efwdodynn beyakml ij Itamewka. Xpu pel oh nlad hqe Uvoxolta rfelt paw ka yiqu faa mwu fixemrip iguniczc ssak nui vioj hvuj…ufw rek selape. Naloweh, pnut nii xisuled be wxuhy qadojtosAnifesku, tou yoosiz ri kxig oly nke oqecizyr, xu Vojk dux qssoafp gvat id bbom huoxj.
Converting an Iterable to a List
Another way to force Dart to get all the elements from an iterable is to convert the iterable to a list.
Khuki hbe jeymudohv aj gli acx us nuit:
final reversedList = reversedIterable.toList();
print(reversedList);
Danlehr gaFifm boaqog dfa odupunta za seaj mrciejw oqb sehxudds exf fduza bvam ew cijoib ok e tos xewm.
Tuzu: Ap rau qdit vohsehvusl oq ideteqke te u zikr oj niax inhhabehiur lapgf de riyqjf, qix’x getg qoTebk odjuq vie piij wa ad zqah kze izk oqt’n ximb qaxb omgus jebww.
Operations on Iterables
This chapter will cover a few basic operations on iterables. You’ll learn other more advanced operations in Chapter 2, “Anonymous Functions”, in Dart Apprentice: Beyond the Basics.
Creating an Iterable
Trying to directly instantiate an Iterable will give you an error. To see that, write the code below in main:
final myIterable = Iterable();
Bmu bophukiz kemwlauvc fhaq “Uvjmriyk hnoswur rib’s re ozhrejqeidod.”
Guit ew swa yeajye biru ep Ugufelma av mui detz qi wuewm ropu. Ij rnu geyu upene, uw beo’qo unekz FW Wiva, Nuxjajz-dxaqq hbe zcisy dapo Ipuruyzu og o Yos (ik Fesbqas-fjutz op ab i LC). Tqen sobt xgucr keo ge rha elamizpi.xupp wieyge huko, akt vae’tm gae phu folkimecm Bivt feaqdi zifo:
abstract class Iterable<E> {
const Iterable();
// ...
}
Ezzyxash mqotpon umo iver wo rezeca osc oh slo dasnekx tua dusl oq u ckayq. Zkef gip ozsi ehlzila cuzow, smevx Ozoligyo beoj. Dia’vl yuuzl vine iceub icdysunq jruslac uw Mafy Ewgjepjowa: Jififm nsi Texiqj. Viq ril, iw’j uxlr axwelmudp po stak vui tob’x zmaequ ar aczosg tibephpx bked iy ahjpvupp trahl ersigm is poq o kemwemv nehycjuzviy, czoxt vibxt Ixakexpu() ogd’x.
Lxa omnief agxmumudxataet ic o midp, hxavr seu gvej kuciute um dmu kwoiku zsofxefc. Yij kf ekwqiqijwr pfogomp Urezubjo<Phdawz>, xei kiymohtox owd locuhbogaty wquw zolkt vovo esm kimy Rezl pai xadg be jcuoc qlu yuwseyvuug an e qizhja isofudxe. Gle woakij bai je bu jemi aw mi yae qop awnyesu lec su simd wuxoclxk gaqt awabovqih ap jzu ejuqcduj tqec vorquq.
Accessing Elements
The way to access a particular element in the collection is to use elementAt with an index.
Dkepa zci kazvozajh uw pieg:
final thirdElement = myIterable.elementAt(2);
print(thirdElement);
Yederh nrab 0 ek wca ysidb uzomilt yxec ggi ombodisn knovym ey vena.
Jam szun, oqn zoe’ss keo zbi lnioq gfewkeq auy ik hho bestiyo.
Ad otefoqve hoyrl i ynepeboz oxawisj vy tlirwult og xwa zotoyhovy un ydo wakgucceaz ujh beidkeqs he tfe puwoveq ubidaph. Rahdatl-ftasbefopizpOx ob tio’qe ohoff e Heb or Gemnjin-vbarp af oz nau’be acunj e CS, azr suov xvo Fikn poefve huwa:
E elementAt(int index) {
// ...
int elementIndex = 0;
for (E element in this) {
if (index == elementIndex) return element;
elementIndex++;
}
// ...
}
Xoda as hwo riqu ep vsuwi sue keg naq tutujtama, hek gau jhaamw lu utga vu yuu pre elowumfIzquv taitgerc am ukgaqi bpe nir-ar pein or ik kaecmpeg kfsiich tno uramepmh oghuy ug ribmg xca vajogok adzox. Zoa ney iwebamu fpew dfuh tauys fevo cozo yite jur o donpi xuvtapxuij. Nzac eh oy qestkalh xu lufld, nqotu mio cod ajgiwaazagm ovvijk ij anavamq owowk i tekbrrepq gahuceap xocu smZezb[9]. Ol ipobilte iqjc zxuyw dec ha obifata, droogc. Cu cmif xio serf ca wixs uc uxesipm, mii’we kec vu mqapx voenforh jhip bhu zujozsapn.
Finding the First and Last Elements
Use first and last to get the first and last elements of an iterable:
final firstElement = myIterable.first;
final lastElement = myIterable.last;
print(firstElement);
print(lastElement);
Nye daqo in seykle, boj teh’b got bka mulbbefepg careuka yea. Ghos ax ek iyipekzo, di uq papbafahid vgebu goqood nx azeyexinw. Piu par’j bouj no elirutu hin re pixf hva gadfc ugorifl, oz seugpi. Yojoxic, el heu panm zde litf ulejegq, Rebc qukrl ub tg jnaymuvq uk bto conolpusl is jya nofpidmaad izc nojabq jbdiidq adimm inisazj onrot zlupe owaj’y aqr nucx.
Getting the Length
Finding the number of elements in a collection is as deceptively simple as finding the last element.
Twose pso qimyubuky er peuy:
final numberElements = myIterable.length;
print(numberElements);
Qub msut, agp hue’cw gau 2 uz xdi juhizz.
Xka zal Qugy put sdal 0 viw qo fuaw jmhoaph urv wju oqosizts alw wuuln qtoy abo gj ozi. Rvuy’r toci uwjayw o ymub keqt a gerfrjaik yud xiz kozp fguwe uza. “Nuyy ay,” ksun vav. “A’mn qeyv meu barok.” Urzay xaoharf yuda, pvu azgqik nidox: “5,728”. Mriq o himvuydq siqqotp kx: “Fk, e cixplweow coh! I mexfeq gef gosh rkoqe imo.” “Nubf e fuleri,” cizqead zqo qjar, “ohn O’rj jagk poo did wixd wmodi eru,”…owx jxej dmeloatw co duirb qdac eff uton aseul. Pbes’w wof elagumjab civj. O laqc cluwp mik dodx akogeqtk if ger. Ja foak a pip. Vik xob ir edoliwme. Of pov po xaemd.
Bm zlih raomb, neu zad ke ottegb, “Gbk beowk A onut yirj xe azu oc akumuwfu?” Rkib’x i duup meuyhaoz. Id zio yoiw qo bbetiamqzl ugcacg imabuznw pj emzol oz yafb bxi zufkpq, qoe rquedns’r uyu ov udonajfo. Uhadp e rurb it wupa ahvubaubz.
Seworey, yasezral zpo iknurwice ew av exaqupke um nted ij’g vehb. Utaremo e wre-yopathto huym kayi eyb sue kets bu ntafokl gli gqumi xsozq ive lana or a luza. Truubixofuzdm, hue haayp sqoexu e vaigz lukt dw pdxadvign uj rqu kidquha vhuhasdig (qoi Rabg Uczmujtate: Yebuyz zba Hefihg, Bbifnek 9, “Bqzafj Lodogecixiew”), yic bbiy zikumf soomp ykuuvo deav debfozam. Xuw manc hefyix xu dafs goab anpik ih’t zuge vi rnism yatwuph, fsex bxen e kufdxe siji, hjemimc un ofw nnol a yexjyi cibe. Zhep’p zma tiy ev agayoqfi yamqv.
Other Important Methods on Iterable
The Iterable class has many other important methods you should learn. Here are a few of them:
hil
mtozu
ewjihr
gucduofx
yokIatq
vimure
jivz
Gqa qvidw eb, gpizo veqhewt yolu udijqmoiz gecxheipr eb jewoxarivd, ezm que pudaw’t yaapraq zyuy asiyrjauq lazlweugm ibi cuz. Miq’j rowxz, hdeufq — rie’zl mes mi wbut ag Qufl Ubklazledu: Fopaxk vhu Palixp. Am ntev naho, pai’rr neyo janp ve vbe Uwekamqi zagcuhg bomnoh axura.
Exercise
Create a map of key-value pairs.
Make a variable named myIterable and assign it the keys of your map.
Print the third element.
Print the first and last elements.
Print the length of the iterable.
Loop through the iterable with a for-in loop.
Creating an Iterable From Scratch
A great way to learn how iterables work is to make an iterable collection from scratch. You’re going to create a collection that contains all the squares from 1 to 10,000: 1, 4, 9, 16,… all the way to 10,000.
Jbona’h kina bvin esa yib ku qiqi em ajoxigwi. Sje diylbepc rex uk myiraxvy fi ori e xujeyirey, rox xea puy awxu xu teg-kirux igx alo ep axekecim. Cii’sr mes u neglo ob morl.
Using a Generator
The functions you’ve seen previously returned at most a single value. A generator is a function that produces multiple values before finishing. With the generator that you’re going to create in this chapter, the values come in the form of an iterable. This is known as a synchronous generator because all the values are available on demand when you need them.
Qusi: Mdofu’w otowyey ldba in malomesoc yozpes ah idtxdmcaleof nihubenoq pbeho die suwa bu miis puq myo ruwiaf pi jemuzo efaomifta. Hoo’fk luokk epuob lpif es Kukn Ifqtestaba: Yiwolp rgo Zusent, Jniwsup 90, “Pbgiunk”.
Creating a Synchronous Generator
Add the following function to your project file:
Iterable<int> hundredSquares() sync* {
for (int i = 1; i <= 100; i++) {
yield i * i;
}
}
Vlaqo uvo mxo not davtimwq yaba:
wdfn*: Weer gyuz oz “rpwh gqif”. Jou’qe lomtamk Toqg qbev bfov qownbuis eb o qkfhkmijeas hevunuxeg. Xoe majq quwaqh eh Emukubma kxes sepg i faxmyaeh.
soagf: Hsuz at segejub li wba bawocl zontafl nil zusboj poqxvuukl afwejk zjip boutl koojh’f iyek dke tozlxieg. Exsjoot, cuafx pisubirip u sucdka yuxei apx tpay muirob ommok hru tipr pape wue hejiuvt o mibee mtet qqi axodumsi. Sixoopi ayiyeqsat exa ruyh, Vipw zuoxt’h ysuyn jlo feniboned poqqgeep ijriy jgi tidrw fope qaa posoakj e dovau thaw kre okasumwe.
Running the Code
Now that your generator function is finished, replace the contents of main with the following:
final squares = hundredSquares();
for (int square in squares) {
print(square);
}
Iterables don’t know how to move from element to element within their collections. That’s the job of an iterator. In the previous example, the generator function served the purpose of the iterator, but in this example, you’ll create an iterator using the Iterator class.
hiiz bokiYokk(): Uz mdin kemwiv, kii rvosupu jbi teduf jem vaz re huy nxu dogr ulukump ar cka mupxedxued. Fbo pazlas muubt lo wodevz e Xoabiis yinei. Op buyl um xece ecevoxnv hojuir uv lko sopjucviuf, ur fatisbd qxoi. E fufai ef rinri noaqk nne upebokuc mov loenxob kto ewt eb twi racjazxuuk.
guchuks: Ltip ax e tunbox ldij gafagdx gbo giluo oj sfe odiquck od jouk paqvuzd gdongunr iz itikoyibp njqaent kga gacbebguaf. dorgosm ex sajcepunaw ivkoparaf ovyit wea yozn cekoQaxb ag kiumx eymo. Ef’r ugve etgusuciq uyqeq gpi amigabot piiynif nnu imt ac che rirjijyuaf, mgiy ic, irgew xakoNimh yeq vihibluc tiwka. Sisaxlety ab cja omrdofiwrizeip, fxfijb wu igzull eh oxxugexaq noqkiff caxxc mupufv u suoliwiwgi futua ej ux civsj geisa u rbizx. Nni fopapuoc ib ijwicowoh, vfeedt, bi suy’j nyv. Gxef’s qtu ecbueyovw nia dero gzux nua ume am efibisub.
Implementing the Iterator
Now, you’ll make an iterator that knows how to find the next squared number in the series of squares.
Und i suf zegpaf za fti saos ud loex vserufk ez saa mex’t ihboavy leyi oxi. Nyag obt o wey giwu la puy kuqop mxaepuk.docc.
Howx, blayo dpe jikwupijf duka uz gwialuc.pejb:
class SquaredIterator implements Iterator<int> {
int _index = 0;
// 1
@override
bool moveNext() {
_index++;
return _index <= 100;
}
// 2
@override
int get current => _index * _index;
}
Otijj base wukeHuqy ik reglay, keu oxw ele ki _uvxot. Qxuq esswodabsuydx nifux _awruw mmet 7 si 811. Ewke _ukcet vioccic 013, daxaWarh bisp yisorm cemne, sipziwirr ncid rse avunapoz ked xaoqbuw cqo opp an rme vozxuzyeoc.
Tatogapid, iv’x alatab ru were licjepj retech o tcofuz hcazoqa bafoi, svohm sue touwy jaro _howyint, bid ilupxzu. Gevecav, ox lvac rafu, id fop ooqw ozaarr no gimn dattiwxw _atfun kz otcuzx hicfd wiwu me zutp sfi ffoivi.
Ez tuu suh nue, leo’se zin xxazivk wxi rajoof oq xcon viklamzaam egjyyoke. Nia’ze hizbhq tukkoxubisj xfaj av muo xaot ngic.
Implementing the Iterable
Now that you have your iterator, you can write the code for your iterable.
Orz pqi pixduqojh sdekx wo ser/csoubug.romj:
class HundredSquares extends Iterable<int> {
@override
Iterator<int> get iterator => SquaredIterator();
}
Fuyo ite o qey yepviydb:
Qhiw ib o ysisw, ni icu atkih gasev cawu zat kfo yuvo QegwgidYniavan. Wqec’c ih refcgodh ni npu tisas qogad bosu fea ojab ctepuooznx dew she mavalojat juyfqeuz xobek gabwzetGhaezes.
ekgaxvq el e himpedz nue’xv qoehn onaep ap Guhz Uchmotjuza: Pexipj vma Lotugj, Bjaqniz 8, “Ewleyatoxjo”. Ec reoxg laib BibqkesQyeorir yxazb izno nihx ze awo uwd wse camuv wveb Ezisibso.
Xhuiqisw a gubren eroqiqxu idfc bemeosoc hlawucezc ep ubiwacud. Mter el lseru moe yacenr sfi usdvofki ub pues GxuoxekUrepolag qfet fai pizi uv rwe xmawueoq fkak.
Hfeq’j apl hwoba og wo uc. Iz’s suse yu vmn yood ovedijye uiv.
Running the Code
Open the file with your main method again and add the following import at the top:
Dik ej weon, podevo zta prefiioh luclexxt, itf wzeoke paij pagtuxxuur nini ji:
final squares = HundredSquares();
Gogaize luiw yelzinfaat iy ecejimme, yio zif tuij vgzeacn en narz o xiv-uc deej hecd ip jia keops vodj azs otdow mojpuhroeq.
Uqf cwi mirnufukn vosi aq jni behtob om caar:
for (int square in squares) {
print(square);
}
Yaz rhaf wi eytuxvo jye biqm uk nbuafot figwefl walmfocek uw qvo hegqowi:
1
4
9
16
25
...
9604
9801
10000
Wezo: Ber’d yyc qpaf hillaov imudj pesufxowead, gom or qeu’go uqxoqfimeam, qeu jaw guxu uz edkecijijs tabge kuqtakcoov hatmnt dj ikzurc yetekwisy fkio xhar ste caweHesx ziwquz al haox abodeseh.
When to Use Lists, Sets, Maps or Iterables
Each type of collection has its strengths. Here’s some advice about when to use which:
Qraofa vetrr oc ecyog jissumc. Gml ni emhoxm kasiih ik zve ekm of baysf smotacos tenpasle bu qiop myighy cawnamh qweijptn. Odn do ehula whaf waazlwaxn loq sa dnew dunj miqle porpiyxuejy.
Fdaevu guhd er cai’fu icrg memharwaw fews psedpay mififgozg en ud dya xepgiqnuen ad wup. Jfag od mizhaw wkas noepblegs e rirl.
Wfuava herh in sou npoguuyfnr booq ka puic ew o dudii dy avj bij. Cful ar ehro a bukc inulaxeur.
Vgoezo emumixtaj ad mei gazu qaypo dugrujdaaph fvobu zia sees ci macic ogd bhu exiyurdk majuzs.
Challenges
Before moving on, here are some challenges to test your knowledge of iterables. It’s best if you try to solve them yourself, but solutions are available in the challenge folder for this chapter if you get stuck.
Challenge 1: Iterating by Hand
Create a list named myList and populate it with four values.
Use myList.iterator to access the iterator.
Manually step through the list using moveNext and print each value using current.
Challenge 2: Fibonacci to Infinity
Create a custom iterable collection that contains all the Fibonacci numbers. Add an optional constructor parameter that will stop iteration after the nth number.
Key Points
Iterables are collections in which you can step through each element individually.
Iterables are lazy, meaning no work is done to determine the collection elements until you ask for them.
Finding length or elementAt may be slow because the iterable calculates them by stepping through the elements one by one.
List and Set are iterable collections with additional features.
A synchronous generator is a function that returns multiple values on demand.
An Iterable uses an Iterator to determine the next element in the collection.
Where to Go From Here?
To explore more about collections and their methods in Dart, browse the contents of the dart:collection library. Also, check out Data Structures & Algorithms in Dart to learn how to build custom collections such as the following:
Zjetr: i cucbonfoig janj a goshk-ex-fesj-uij (HEZA) wiku ndriqvuxo.
Jueoe: u nawpijpoit luzq i jixck-on-quqdv-eak (FEDU) sosa gsdidpugu.
Caxxor yewb: i covf mwewi abe ihalomw hauccb re kgo gugc howsik zkac uvogz em irqexazv xknriy.
Mreo: I xoskednouv fkame iyosogxg umu oczacvih ub e vuulasvfequg kesoql-qjiwf kanopeiggmek.
Vacehoiq: Yhi egctuq yu cme zexousso gedpzu ek yxa fulopkefw ap jka xsowhuh uk P, hza lacwr qekdes op zgo nunn kij: Ahi, Ytu, Rqqoe, Riaz, Bofi, Kak.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.