SCRIPTING:

Anna Falchi in an Angelo Gigli (c) picture

LEAP LOOP WITH OR WITHOUT PATH
How to loop and rearrange an array after a pattern (path) or a jump amount, or both, instead of the usual unary increase, being sure that when the end of the array is reached the script can manage properly.
Test form at bottom of page.
December 2001
{ @ }

The model above is Anna Falchi [an Angelo Gigli photo]
LOADS OF ANNA FALCHI ON THE NET


LEAP LOOP FUNCTION MEANING AND ITS CODE
What's a leap loop for and why it may be useful?

I bestowed this script the name of leap loop for I found it fashionable enough a name, and fairly descriptive.
This function implements a procedure that although may appear of no use to those scripters whose idea of a script is "whatever, being utterly unable to stretch above 5 lines of codes, is quite able to flaunt precisely because of this", none the less is a procedure that may help a lot those scripters who may face more demanding challenges than relinquishing a prompt dialog box on the screen.
The idea is this: you have to loop an array in order to pick up its entries in a different order, and such order must follow a pattern: in such case, this pattern may be given by two factors:
  1. You want that each time an entry of the given array is picked putting in between an x amount (such as: one entry each 3)
  2. You want that this procedure picks entries following a scheme (such as: 1,4,5,29)
  3. You want... both things: a leap that also sums up a path each time it iterates, so to produce for instance exponential jumps
Apparently, all you may need would be either a loop with some above than unary increase or, may be, just a direct addressing of the specific entries you want.
But there is a case when you might need something like this leap loop script: that is, when you want that this pattern or jump or combination of a pattern plus a jump is able to:
  1. Detect when the end of the array is exceeded and then start back from the beginning of the array again, keeping track of the amount it needs to extinguish the required jump (that is, if I'm jumping 10 by 10 but the array has only 6 entries, you want the first jump grabs entry 4, for 10-6=4: and must go on with this logics).
  2. You want that when an entry has been already picked, it cannot be picked again: in such case the script must be able to detect the immediately subsequent available entry of the input array which has not been picked yet, and pick that one restarting the pattern leap loop from there after it has picked it.
  3. What is important to understand is that this function would not leap starting always from the beginning, but when it picks an entry, will start the subsequent attempt to grab a next entry using the latest entry position it was on as its new starting point. You'd keep this in mind, or you might wrongly argue the function doesn't work: moreover, doesn't pick twice the same entry! So, if on an input array like [1,2,3,4,5,6] you jump by 3, first pick is number 4: next jump leaps forward from slot 4 and thus should have got 7, but there is no 7 for array has only 6 entries: so now it is out of boundaries by 1 (one), but the function can understand it has to restart and thus grabs 1; next it would come across 4 once again but since 4 has been already picked, the function moves on to 5 (switches by one, that is, in such case. You can learn more in the comment section below about this behaviour and its wise reasons), and finds itself out of boundaries again thus understands it has to grab 2, and so on until all entries have been recollected in the new order imposed by the path or leap argument or both if both are put in place.

    Such logics applies also to a path argument - that is: an array passed as a path argument, that dictates the amount of the jump at every iteration, like myArray=new Array(0,3,6) would mean jump of zero at first iteration (grab first entry, that is), then jump by 3 at the second then by 6 at the third and then back to a jump by zero and then by 3 and then by 6 again...

This your case? This your... long on-looks script then!

The model below is Adriana Skleranikova
LOADS OF ADRIANA SKLERANIKOVA ON THE NET
Adriana Skleranikova
The model above is Adriana Skleranikova
LOADS OF ADRIANA SKLERANIKOVA ON THE NET


Some Comments
How it works and can work

There is an ample validation which may appear annoying but I wanted the function to be able to take care of itself as much as possible.
It requires one argument, an input which must be an array (no validation on this), and either one or more of the following arguments. Basically, the validation takes care to manage the following possible cases and/or exceptions:
  • On the whole: we verify if an input argument has been passed and if leap is not a number, in which case we assign to it the default value of zero.
  • We then check whether path is an array (since it should be: if you want your picks from the input array would follow a path, you have to define such path as a list of numbers in within an array passed as an argument to path).
    If path is not an array, and also leap equals zero, we return the input for there is nothing to do.
  • If path is not an array and leap is equal to something higher than zero, we assign to path a placeholder array of one single entry which holds zero as its unique value, and we proceed thus to leap loop using just the leap amount, for a path whose unique entry is zero, would neither disturb the process nor would tarnish it but would mesh smoothly.
  • Path is an array, or an object at least: we set the missing leap argument to zero in order to let the script scour the input array following only the given path
  • Path isn't an array: if also leap is 0, there is nothing else to do but to return the original input.
  • Path is a number, we assume the scripter meant to pass only two arguments: input and leap, thus we assume he meant to pass a leap since he passed a number: we accordingly set leap to the path passed number, and we set path to a one entry array which holds a zero, so that the script can run smoothly but without being affected by a path which actually is equal to zero.
  • The startAt argument is entirely optional; by setting it to a value higher than zero (being zero the index of the first entry in the input array), leapLoop will start its tasks on the array by that given entry. Example: if startAt=3 and input array= [a,b,c,d,e,f], leapLoop will tackle the array starting with letter d, in fact: (a=0, b=1, c=2, d=3, e=4, f=5).
    startAt defaults to zero.
    If leap argument is set to zero, and the startAt argument is set to something higher than zero, the leapLoop functionwould reproduce an array whose first half starts with the input entry at startAt level and will go on until it finds an end, and the second half would be the missing entries that were before the startAt position in the original input array: example: leap=0 startAt=3, input=[a,b,c,d,e,f]: output is: [d,e,f,a,b,c];
    By all practical uses, you won't need to set a startAt argument: you just keep in mind such an argument exists in case one day you face an sudden necessity to perform a leapLoop by a position different than the beginning of the input array.
    StartAt also allows you to perform a trick: if you set it to the length of the input array less 1 (input.length-1) you may yield interesting outcomes: feel fre to test in the form.
  • The range argument is entirely optional, and is set to the input array length by default, since I argue you want to take really avail of the features of a leap loop, namely to scour the array restarting from the beginning until all the entries have been rearranged accordingly to the leap or path (or both) arguments.
    In any case, you can set range to some number above zero, and if so the function will stop when an array whose length matches the given range is attained. If range value is higher than the input array length, range is reset to such length.
    Moreover, if you pass range argument as a string (whatever) but not an empty string (a set of two apex, like 'string') for an empty string may be read as a false value (I can assure you it can happen, althouhg javaScript should not consider an empty string as a false boolean: perl and Php do that, not javaScript. None the less, it can do! one of the very rare occasions where passing a string building it with the constructor new String() would make sense!!) the function will go on performing assuming that it must stop at a, so to say, special type of range: and that is, as soon as the cumulative sum (see variable named jumpSum) of all the previous leaps has surpassed the length of the input array. So a range argument passed as a string means: do not start leaping from the beginning, just stop once you've reached the end of the input array!

    Well, you do not have to understand now what all these weird features are for: here you have a leap loop function: use it if you face the problem; one day you will wonder what if you doesn't just need a leap loop but also to stop at a certain condition, and guess what: my function will be still there.
     

  • The starkOutput is optional as well: if set to 1, would yield an array whose each entry is not the letter (object) in the input array, but its index position after all the leapLoop rearrangements have been performed.
  • Remember that if you want to set an argment like, say, range or starkOutput but you do not want to set the previous ones, you have to pass them as zero.
  • leapLoop accepts negative numerical values (if so, performs backward) passed as arguments, except for the range argument, which if numerical must be positive.
We then initialize some variables: in order to avoid the leap loop to pick twice we make a copy of the input array and we assign to each entry the value of zero: such values will be updated, when the script goes to its main core, to number 1 whenever a corresponding entry in the input array is picked by the leaping loop (a trick already used in SORT ARRAY 1, KEEP SYMMETRIC ARRAY 2 at point 6).

We make such copy using a for in loop, which handles the entries of an array like properties as we know (you may want to read on this issue my file on HASH TABLE FROM ARRAY TO IMPROVE LOOPING, towards the end of that page).

Then I use a while loop: it works smoother in JavaScript than recursion, for a deeply recursive function may easily erode your browser's stack resources. Until output's length is not as long as input's, we won't cease the leap looping procedure: this will grant you you'd get a thoroughly redrawn version of the input array (a copy, anyway: original array won't be affected): if you then need a subset of such outcome, it would be up to you to slice a subset from the outcome.

I verify by the pathIndex variable agency, that the looping of the possible path grabs subsequent indexes of the path array (which is involved in action even if it was not passed in the validation process, and in such case has been put into place as a one entry array which holds zero, so its possible absence won't disturb the function in case you meant to omit a path that the inner workings of the script would none the less require and would assume present anyway).

jump is the variable name that will keep track of the leap plus the current path index level (if provided a path), for the function would even sum the leap to the path currently grabbed entry if both arguments are passed!

While and whenever jump happens to be higher than the available input array length, jump variable gets shortened by an amount equal to the input array length so that as soon as it is not higher any longer, jump can reposition itself correctly from the beginning (Ok, I mean: if jump=10 and length of input=7, 10-7=3: first entry to grab is thus the one at slot [3], and so on...!)

We make now an important check: we see whether we have already grabbed the currently candidate entry: if so, we add one unit to jump, and we won't update it at the next iteration of the loop (that is: we won't add either the leap amount or the path index): we seek in such fashion to spot the first subsequent available entry which has not been picked yet, and this can be performed in a way consistent with our puropse (avoding an infinite loop, such it is) only and exclusively by either adding or subtracting 1: whatever idea of adding or subtracting a number higher than one, would run into very very high risks of falling into an infinite loop (By the way, if you want an approach that instead of adding 1, subtracts it, well: reverse the input array before passing it to the leapLoop routine!).
Without such approach, you might easily enter, as we said, an endless loop, for if the scripts finds once an entry it already picked, odds are that soon it will came across that same entry again, and would then get stuck: a chance that may be approaching quickly when several of such already picked instances would increasingly populate the copy array.
I assume that if an entry has been picked, and maybe also the subsequent one, you may surely want to go on with the next free one, and to keep the current pathIndex level as long as it has not been usefully employed to actually grab an available entry.

You may want to see a few instance of invocations of this script: well, let's assume that path is an array held by a variable whose name is myPath (and whose length has no specific constraints: can exceed or be outstretched by the input as well, but if you include a path array, it must have at least one entry: makes sense doesn't it?), such as:
myPath=new Array(2,5,7,5,2)
and that an input array may be:
myInputArray=new Array("foo1","foo2","foo3","foo4")

A few invocations may look like (whereas you see the term myPath it's a placeholder for an array holding your path of choice passed as the path argument):


leapLoop(myInputArray,2,myPath)
would follow a path and jump by two at the same time
leapLoop(myInputArray,3)
would just jump by 3
leapLoop(myInputArray,myPath)
would just follow the path
leapLoop(myInputArray,1,myPath)
both leap and path: sums leap with a subsequent mypath entry at each loop, and therefore jumps by the yielded results
leapLoop(myInputArray,1)
would jump by one: actually, would shift all entries by one!
leapLoop(myInputArray,1,0,3)
would just jump by 1, and gets a range limit of 3. Note that the path argument has to be passed anyway, and is this time passed as zero in order not to set it (this assuming you want a range but without following a path. If you would have wanted a range but also to follow a path, all you would have had to do would have been to pass the myPath array again)
leapLoop(myInputArray,1,0,"w")
as above, but this time a string has been passed as range argument: it stops as soon as the cumulation of the leaps has surpassed the input array length: that is, won't start back from the beginning!
leapLoop(myInputArray,1,0,0,12);
startAt argument set to 12 so starts from entry at index level 12, no range argument set (but you could have: whatever the case, if you set startAt, you have to pass rtange, at least as zero).
leapLoop(myInputArray,1,0,0,0,1);
starkOutput argument set to 1: returns array of indexes.
You can imagine all the variety of combinations by using positive numbers instead of zeroes.


AN ACTIVE EXAMPLE
A small test

TEST THE LEAPLOOP
[ zero is first entry. Accepts negative numbers ]
STARK? »
 
JUMP» START at» RANGE»
 

 
Salma Hayek
[ background: M. C. Escher ]
The model above is Salma Hayek
LOADS OF SALMA HAYEK ON THE NET
TOP of PAGE