Decrementing voor lus in coffeescript

Ik weet hoe ik een ophoger moet maken voor lus in coffeescript, zoals:

Coffeescript:

for some in something

Gegenereerde Javascript:

for (_i = 0, _len = something.length; _i < _len; _i++)

Hoe maak ik een decrementering voor loop vergelijkbaar met deze in Coffeescript?

for (var i = something.length-1; i >= 0; i--)
26

6 antwoord

EDIT: Vanaf coffeeScript 1.5 wordt by -1 syntaxis ondersteund.

Eerst moet u uzelf vertrouwd maken met het sleutelwoord door , waarmee u een stap kunt opgeven. Ten tweede moet je begrijpen dat de CoffeeScript-compiler een zeer naïeve benadering van lus-eindpunten inneemt (zie uitgave 1187 , waarnaar Blender gelinkt heeft), wat betekent dat

for some in something by -1 # don't do this!!!

zal resulteren in een oneindige lus-het begint bij index 0, verhoogt de index met -1 en wacht vervolgens tot de index something.length raakt. Zucht.

U moet dus in plaats daarvan de syntaxis van de bereiklus gebruiken, waarmee u die eindpunten zelf kunt opgeven, maar ook dat u zelf de loopitems moet pakken:

for i in [something.length - 1..0] by -1
  some = something[i]

Uiteraard is dat behoorlijk rommelig. U moet dus overwegen iterating over iets.reverse() in plaats daarvan. Onthoud dat reverse() de array waarop u het aanroept, wijzigt! Als u een array wilt behouden, maar erachterwaarts wilt itereren, moet u deze kopiëren:

for some in something.slice(0).reverse()
50
toegevoegd
+1 voor .slice (0) .reverse() , precies wat ik zocht!
toegevoegd de auteur Dan Abramov, de bron
@RicardoTomasi U hebt gelijk dat het zonder de door -1 werkt, maar het is minder efficiënt - kijk naar de gecompileerde uitvoer voor beide. Vanuit het perspectief van de compiler is something.length mogelijk negatief, dus de stap is mogelijk 1 of -1 .
toegevoegd de auteur Trevor Burnham, de bron
@davidchambers True, vanaf CoffeeScript 1.3.1.
toegevoegd de auteur Trevor Burnham, de bron
Merk op dat array [..] een afkorting is voor array.slice (0) .
toegevoegd de auteur davidchambers, de bron
Ik denk dat je zelfs de -1 niet nodig hebt. voor i in [sth.length-1..0] werkt prima
toegevoegd de auteur Ricardo Tomasi, de bron
@Robert goede vangst. voor i in [sth.length-1 ...- 1] "fixes" die: D
toegevoegd de auteur Ricardo Tomasi, de bron
@RicardoTomasi U hebt de by -1 nodig als sth een lege array is. Anders zou de lus twee keer meer lopen dan verwacht (nul keer). Eenmaal voor -1 en één keer voor 0 .
toegevoegd de auteur Robert, de bron

Vanaf coffee-script 1.5.0 wordt dit ondersteund:

for item in list by -1
  console.log item

Dit vertaalt zich in

var item, _i;
for (_i = list.length - 1; _i >= 0; _i += -1) {
  item = list[_i];
  console.log(item);
}
38
toegevoegd
Je kunt ook de syntaxis element, index gebruiken, zoals: console.log "# {item.toString ()} op index # {index}" voor item, index in lijst door - 1
toegevoegd de auteur glampr, de bron

Een andere versie is net voor de goede orde:

i = something.length
while item = something[--i]
  #use item

(zal valse waarden doorbreken)

2
toegevoegd
deze breekt niet bij gebruik over lege reeksen
toegevoegd de auteur david, de bron

Er lijkt geen elegante manier te zijn om achteruit te lopen.

I checked the GitHub ticket regarding this, but it has been closed: https://github.com/jashkenas/coffee-script/issues/1187

De syntaxis was:

for some in something by -1

Maar het is in recente versies verwijderd. EDIT: het werkt nu (voor 1.6.2 @time of edit)

1
toegevoegd

Idiomatische manier (van documenten ) in de trant van:

lst = ['a', 'b', 'c']
for n in (num for num in [lst.length-1..0])
  alert lst[n]

(bewerkt na de opmerking van @ Trevor)

Bewerken

Hoewel, als de prestaties kritisch zijn, dit gelijkwaardige maar misschien minder esthetische fragment minder resulterende JavaScript zal genereren:

lst = [1,2,3]
i = lst.length
alert lst[i] while i--
0
toegevoegd
Umm, dit werkt alleen als lst is [1,2,3] . Als u bijvoorbeeld lst = ['a', 'b', 'c'] gebruikt, blijft de uitvoer 3 , 2 , 1 .
toegevoegd de auteur Trevor Burnham, de bron
Juiste, vaste code. De 2e versie is echter correct.
toegevoegd de auteur Jacob Oscarson, de bron

Voor een decrementering, index-gebaseerde for loops, kunt u gebruik maken van:

for i in [0...something.length].reverse()

Dit verwijdert de rommel @TrevorBurnham is een probleem met het opgeven van endpoints zelf.

Wanneer something.length is 0 , is dit equivalent aan

for i in []
0
toegevoegd