OVERVIEW OF THE FUNCTIONS, AND SIDE SNIPPETS
|
|
What the main functions do, and minor function(s) to aid the bigger ones
|
«Rebuffing into the hi-fi Element»
[by a dream of mine]
«There is no incongruency; Here the inner Chambers are referred, There the outer Ones»
[Qabbalah: The Festive Offering]
FEATURED SCRIPTS |
perfectSequences [minor function] |
Finds sequences in an array perfectly matching an input like [A,B,C] or an input with fixed interpolations like [A,x,x,B,x,x,x,x,C] |
arraysToList [snippet function] |
Gets arrays and ranks them as entries of one parent array |
sharedEntries [major] |
Finds entries in common in a list of Arrays |
looseSequences [major]
|
Finds sequences in a list of Arrays belonging to a group like [A,B,C] regardless of - Interpolations
- Order: namely [B,A,C] would do as well!
|
strictSequences [major]
|
Finds sequences in a list of Arrays belonging to a group like [A,B,C] regardless of:Order: strictly [A,B,C]: same elements but appearing with a different queueing order are unfit.
|
pertinentItems [minor function] |
Gets an input array and an array of elements to search for, and returns two arrays one collecting the matching elements and another the indexes in their original positions inside the input array.
Is functional to use the output on fullRangeCollection [this link opens new window].
But for more on this see below |
looseSubSequences [major]
|
Finds sequences in a list of Arrays belonging to a group like [A,B,C] regardless of:- Interpolations
- Order: namely [B,A,C] would do as well!
Finds them counting in subsequences as well: namely searching for [A,B,C] on [A,B,A,B,C] would report: [A,B,A,B,C] and [A,B,A,B,C] and [A,B,A,B,C] again
|
The functions are geared to perform/find the following:
sharedEntries(): Given a group of arrays, find the shared elements (by shared we mean those elements/entries that recur in all of the passed arrays: if they recur only in some of the passed arrays they are certainly shared among a few of them but not among all of them: the script takes into account only those entries present in all of the passed arrays, namely performs a check for an authentic sharing).
looseSequences(): Given a group of arrays and provided you have already found the common elements (via the previous subroutine), you can also find the patterns.
Example: if we have in a group of passed arrays 3 numbers which are shared (let's say they are: 5,7,8), you can find the type of sequences these shared numbers recur more often: instances: [7,5,8] vs [7,8,5] vs [8,5,7] vs [5,8,7] ecc...
So looseSequences is loose insofar given a pattern to look after such as [5,7,8] it reports all the sequences where such numbers recurs, independently of the order they recur, ok?
IMPORTANT: these sequences in all the functions featured in this file, ignore any interpolations : that is, they are not linear sequences, but they only take into account that for the shared group, say [5,7,8], we have sequences in the passed arrays where, like in the function featured after this and named strictSequences, 5 is before 7 and 7 before 8, but regradless of how many other entries may be between them: thus [5,7,8] is a sequence which reports a matching sequence also in an instance like [5,6,7,8]: see, there is a 6 in between, but what matters to the script is that the overall sequence matches regardless of what is in between (that is: 5 before 7, 7 before 8. Or all those sequences where, for instance, 7 is before 5 and 5 before 8 like [7,x,x,5,x,x,x,x,8]).
A NOTE AND A MINOR FUNCTION (perfectSequences)
|
If you're interested in matching sequences without interpolations (sort of "perfect sequences" so to say), it is a somewhat less challenging task, and therefore this long file is not particularly concerned with it.
Anyway for your convenience here is a minor function named perfectSequences that detects all the sequences in an input array that match perfectly with a given input sequence and imposes no interpolations to report a match.
It takes 2 arguments: a simple array (and note: not a list of arrays like all the other scripts featured here would require) which is the input array to scan, and a second array which holds the sequence.
It returns a linear array whose each entry is a Number: each such number represents an index offset in the input array where the inception (the beginning, the first index for each lot, that is) of each matching sequence found (if any: if none it just returns an empty array) has been detected:
It can also work to accomodate searched sequences that must follow a specific order as usual but should also allow in between the listed element for a precise amount of whatever interpolations, as long as such "whatever" is recurring in the given amount: example: you may want to look for a pattern like this: number 1 then whatever thing but only for one time, then number 2, than whatever for one time, then number 3; sort of: [1, X, 2, X, 3] which obviously enough could have been whatever furtherly complexified case like say [3, X, 1, X, X, X, X, 2, X] regardless of why you may want to look for such a pattern.
Well, perfectSequences can accomodate such latest patterns too: you include in your second argument to pass (sequenceArray in the codex) as many wildchars you prefer as placeholders where I used the Xs above: the wildchar you choose should be something you're absolutely positive is not inside the entries of the first argument namely inside the input array.
Once you have introduced your chosen wildchar inside your second argument sequenceArray, you do pass this chosen wildchar as a third argument to the function, and the script would work out the rest reporting only the offsets of those sequences that followed that precise order and allowing only those precise amounts of "anonymous" interpolations.
Instance:
perfectSequences(ARRAY, new Array(1, "#", 2, "#", 3), "#")
When you pass the third argument, remember that as usual in javaSCript if it is a String, it should be passed in between quotes.
Please do not pass the third argument if you do not need to include in your second argument specified amounts of interpolations.
|
Perhaps it should be stressed that these sequences are counted in only if they appear in the arrays (this means: if a residual combination would be, for instance, [8,7,5] but such sequence never appears in the arrays, it is obviously never reported).
If by chance you're interested in a slightly different topic, namely finding the amount of all the possible combinations given an input, you may want to peek at the function named fullRangeCollection in this file.
Also, you may have inside the arrays sequences which are palindromes (namely sequences that can be read in both directions): [5,x,8,7,8,x,x,x,5], which would potentially contain two matching sequences at least: [5,8,7] and [7,8,5] (and even [8,7,5] for the record): the looseSequences function would detect them, thus possibily reporting 2 mathchng sequences for an array where apparently there would be insufficient matches to produce the match: instance searching [5,7] on an array like [x, 5,x, 7,x,x, 5] would report 2 matches: [5,7] and [7,5].
even if apparently there are only 3 elements in the array and therefore theorically insufficient to produce 2*2=4.
strictSequences(): it is similar to looseSequences and differs in this: whereas looseSequences would both ingore the interpolations and would gather the sequences independently of the order ([5,7] would report both [5,7] and [7,5]), strictSequences would instead still ignore the interpolations, but would report only those matches that are exactly of the order [5,xxx,7]: namely 5 before 7 given the provided order for the match to look for.
looseSubSequences: like looseSequences but as soon as a match is found, would restart nearly from the beginning to report alternative matching subsets: example: searching for [A,B,C] on [A,B,x,x,B,C,x,A,C,x,x,C,B] would report as much as follows:
- [A,B,x,x,B,C,x,A,C,x,x,C,B]
- [A,B,x,x,B,C,x,A,C,x,x,C,B]
- [A,B,x,x,B,C,x,A,C,x,x,C,B]
- [A,B,x,x,B,C,x,A,C,x,x,C,B]
- [A,B,x,x,B,C,x,A,C,x,x,C,B]
Since the
scripts to extract the shared (identical, that is) entries in an array need to pass as an argument a list of arrays, you have to use first another (small) snippet of code that will heap all the arrays into one big array of arrays; here it is:
You just pass to this snippet function a list of arguments, each argument one array that you want to be compared with the subsequent ones, and this subroutine will heap them in one single array whose each entry is an array itself. This trick will allow you to pass only one argument to the recursive subroutine.
Example, given three foo foo arrays like:
var arr1=new Array("five","two","three","four");
var arr2=new Array("one","two","three","four");
var arr3=new Array("five","six","two","seven");
You can pass them to the snippet function in this way:
arraysToList(arr1, arr2, arr3);
which would produce one bigger array whose each branch/entry is one of the passed array, which is the data structure wanted by the following functions to pass them the arrays meant to be scanned.
SUBROUTINE TO FIND MATCHES IN A HEAP OF ARRAYS
|
|
This is the first script. It yields as a result one single array where are listed only those entries that recurred in all of the arrays passed to the screening of this subroutine
|
Here is your first subroutine:
[and by the way the banners you see are for free: believe it or not I just love the artistic effect of this pop-art like patchworks and
I uploaded them without any solicitation! I understand the conception is new and unheard of. When have you seen things advertised this eye-striking and moreover for free and in somewhat cultural a framework? So believe it or not, but here it is the fact before your nose: some guys just happens not to do it for bucks!]
|
Above: an a Joan Miro painting - Still Nature with a Shoe , 1937 |
|
|
|
|
|
|
|
|
below: an a Joan Miro painting - Bird, Insect and Constellation , 1974 |
|
When invoking it you will use the arraysToList() subroutine as an argument of the sharedEntries() subroutine itself, including in within the arraysToList() subroutine your arrays as its own arguments; that is:
sharedEntries( arraysToList(arr1,arr2,arr3) );
sharedEntries returns a simple array whose each entry is a shared element.
THE FUNCTION TO FIND SHARED SEQUENCES AFTER A LOOSE PATTERN
|
|
The first function to find the sequences regardless of the order: it is enough the searched groups of items elements are present, regardless of their order and of interpolations. (January 2003)
|
I deviced all the following scripts after having read something in genetics about the Hamming Sequences/Distances namely sequences in DNA components that are identical after some casual interpolations have been stripped off. I found the idea intriguing and thus, elaborating on this simple hint (I am not a genetist!) I produced some scripts that seem to meet, or at least to tackle, this challenge.
The looseSequences codex first:
This function wants two mandatory arguments, the first the usual list of arrays arguably passed by the agency of the arrayToList() snippet function, and a second argument named sequenceArray which must be a standard array of all the elements whose possible presence in whatever permutations you want to ascertain in within each array passed as first argument.
Examples of invocations:
looseSequences( arraysToList(arr1,arr2,arr3), new Array(5,7,8) );
or:
looseSequences( arraysToList(arr1,arr2,arr3), new Array(5,5,8) ); //that is: search for any sequence where -for instance- two 5 and one 8 are present
or, in case you want to see all the possible permutations of the shared entries (but note that the script is flexible and doesn't require in itself that the entries you search for are shared):
looseSequences( arraysToList(arr1,arr2,arr3), sharedEntries( arraysToList(arr1,arr2,arr3) ) );
or, probably nifitier:
var foo=arraysToList(arr1,arr2,arr3);
looseSequences( foo, sharedEntries(foo) );
|
Keep in mind that the function looks for sequential matches, not for strict matches: thus searching for [5,5,7] would report as matches both [5,5,7] and, say, [5,7,5]: in other words what you ask with this function is: «find me a match where we have 2 fives and one seven, regardless of the order they are: it is enough inside an array I have them, and I want now to see what sequences they occur after and if these sequences, regardless which they are as long as they include all the listed numbers all the times I listed them, recur in more of the passed arrays».
Got it? This is why it is... loose. |
There is a third argument you can pass if you want and it is called noPalindromes: if passed as number 1, the function won't check for palindromes (which it does by default): particularly, keep in mind that the script by default search for palidromes only in the last possible match; in other worss if you have as array like:
[1,2,3,1]
and you search for 1,2,3 the script would report [1,2,3] but not also [2,3,1]: for this type of behaviour, namely scanning also sub sequences inside the already found sequences, you can use the looseSubsequences function furhter on on this page. But on:
[1,2,3,1,2]
the script would report [1,2,3] and also [3,2,1] by default: namely when it detects that the last scanned entries (in our case after 1,2,3 they would be again 1,2) were on the verge of making a match, it reports the palindrome completeing this last and eventual match considering it a special and moot case. To skip this behaviour, pass noPalidromes as 1.
The function returns a somewhat complex output, in order to let you gather or isolate from it all the data you prefer.
Now, be ready to be somewhat puzzled, probably: such output is an associative array, namely an array whose indexes are not necessarily numerical indexes, and in our case each index of the returned associative array would most likely be an array itself (yes!) representing a found sequence.
Although it may seem puzzling to you, it is absolutely legitimate: the indexes of an associative array may well be an array themselves!: instances in case your sequenceArray input array was [5,7]:
output[new Array(5,7)]
output[new Array(7,5)]
If you're new to this, please try to overcome your bewilderment as soon as possible: in within a bracket set whatever data type is fit to work as an index, and consequently even an Array itself!
The main consequence brought about by this type of output is that, when returned, it cannot be scanned or addressed by a numerically indexed loop, but needs (in javaScript) the for-in loops:
Example:
var foo=looseSequences( arraysToList(arr1,arr2,arr3), new Array(5,7,8) )
Now foo holds the output, and is therefore an associative Array: to grab all its entries:
for(var X in foo){
// X= the sequence as an array
//tehrefore also X[number] is one entry
// foo[X]= list of entries for combination X
}
Note:
The browser named Opera may have problems with associative arrays at least up to version 6 for a well acknowledged Opera issue (that is, acknowledged Opera shortcoming, not a script problem): more on this Opera shortcoming. |
Once you can scan the output, each entry of the output which as we saw corresponds to each found combination, is another array, this time numerically indexed, holding all the inputs where such combination was found.
Thus:
output[COMBINATION][x]
In output[COMBINATION][x], the [x] here stands for a numerical index pointing at a structure that gathers data on each found item including such COMBINATION.
This latest structure is again an array but of only
3 entries [therefore from index 0 to index 2 included], each representing what follows:
- output[COMBINATION][x][0]=a Number representing, for the given array where the combination has been found, the position of such array in the list of arrays you passed as the first argument to scan (actually this feature is useful only if listArray is stored as a global variable too).
- output[COMBINATION][x][1]=an Array, namley the same array where the match has been found in; consequently output[COMBINATION][x][1][Y]=an Array entry, and could be whatever data type, depending on what was in the originals.
Attention: such output[COMBINATION][x][1] arrays are likely to entertain a pointer-like relation to the originally passed listed Array, thus if you change them also the possibily still globally defined array would mirror such changes - and vice versa (for more on these apparently strange phenomena: Understanding Pointers in JavaScript)
- output[COMBINATION][x][2]=an Array which is collecting the Index position of each match, in the sequence referenced as output[COMBINATION][x][1].
consequently output[COMBINATION][x][2][Y]=an Array entry.
To fully appreciate the meaning of this I can produce the following example:
to simplify we assume you passed a list of arrays containing one single array (a perfectly legitimate move by the way: a list of arrays can contain whatever amount of arrays even just one) and we imagine it was [6,5,0,7,0,0]
Then we imagine you search for groupings including: new Array(5,6,7)
After being run, the function has located only one example where such numbers where listed:
new Array(6,5,7)
See, it contains all the passed number, but in the only order found in the given array (looseSequences searches for whatever matches the passed items, regardless of the order).
So output[new Array(6,5,7)][2]=[0,1,3]
whereas [0,1,3] are the index positions inside the array [6,5,0,7,0,0] where [6,5,7] have been located (and yes, the order preserves the symmetry between the two elements: [0,1,3] --> [6,5,7] means 6 is in position 0, 5 is in position 1, and 7 in position 3 in regard to such positions inside array [6,5,0,7,0,0]. Got it?).
This type of returned structure is likely to appear slightly disaggregated to you, at least insofar multiple matches on the same listed array are reported as independent entries despite the listed array they recur on is the same.
This has been intentional: aggregating also by array after having aggregated by combinations, would have implied to branch the structure by two more furhter levels possibly, thus requiring at times something like five indexes in a row to access one element: that was a bit too much to my eyes too, and I chose to swap some aggregation by some simplicity.
To count the amount of arrays carrying a combination you can thus just loop the:
output[COMBINATION]
and update a count each time the entry output[COMBINATION][x][0]
is a number not met before.
THE FUNCTION TO FIND THE SHARED SEQUENCES AFTER A STRICT PATTERN
|
|
The second function for the sequences: finding a pattern but also following the precise order it has been passed although still allowing interpolations. (January 2003)
|
The best way to understand in what this version of the above function differs, is to consider the following:
The previous function searched for patterns regardless of their order and regardless of interpolations: therefore if you were searching for [5,7], as we saw whatever like [x,x,5,x,x,7,x] or [x,7,x,x,5] would do.
Conversely, in this current function the interpolations are still allowed, but the sequence regardless of the interpolations must be strictly, in our example, [5,7]: that is, it will not report [7,5].
The strictSequences codex:
So: arguments are 3 and identical to looseSequences and all that has been said there about palindromes applies here as well: by default they're counted in: instance, searching for [A,B,A] on array:
[A,B,A,B,A]
reports by default two matching ABA at indexes 0,1,2 and 2,3,4.
The returned output is in this case much simplier though: since the sequence you're searching for is a strictly determined sequence, it is not possible that different combinations of the passed entries may have to be accounted for, thus the returned output has to account for one single instance of sequence: the passed one. This greatly simplify the output, which takes the shape described as follows:
It is an Array.
Each entry is another Array on its own, each carrying the following data:
- output[x][0]= a Number, representing the index position of the passed arrayList argument Array, where the matches have been located (instance: if you pass a list of 3 arrays and a match is found in the first -index zero- and third -index 2) array, this number will be 0 in one output[x][0] entry and then 2 in the other output[x][0] entry.
- output[x][1]= an Array, namely its entries are in the line of output[x][1][y].
Such array is the same array as the input array where a match has been found.Attention: such arrays are likely to entertain a pointer-like relation to the originally passed listed Array, thus if you change them also the possibily still globally defined array would mirror such changes -and vice versa (for more on these apparently strange phenomena: Understanding Pointers in JavaScript)
- output[x][2]= an Array, namely its entries are in the line of output[x][2][y]; such array is a list of numbers each of them representing the position in the array output[x][1] where the matches with the passed sequences have been located.
If no matches have been found, it returns an empty Array.
THE FUNCTION TO FIND SHARED SUB SEQUENCES AFTER A LOOSE PATTERN
|
|
The third function to finds loose sequences, but finds all of them namely counting in also sub sequences. (January 2003)
|
This function is an extension of the idea of looseSequences (and by the way note that the name loose Sub Sequences è case sensitive) and unlike the "simplier" looseSequences script, this one does the following:
searching for instance for a pattern [A,B,C] on an Array like, say, [A,C,B,A,C, B] it reports as matches:
- [ACB] from [A,C,B,A,C,B]
- [CBA]from [A,C,B,A,C,B]
- [BAC] from [A,C,B,A,C,B]
- [ACB] again from [A,C,B,A,C,B]
Note that it does not collect things like [ A,C,B,A, C, B], namely it takes in the sequential matches, but it grabs only the shorter and most immediate in range.
If by chance you're really interested in the more thorough of these possible reports, namely in checking all the elements I suggest the following procedure:
- firstly isolate all the pertinent elements by your input array, both values and indexes, using the following snippet function:
That snippet takes 2 arguments: the first one array of the elements to scan (and note: not a list of arrays), the second an array of the elements to search for, which we call now sequenceArray.
It returns an array of 2 entries (output is a placeholder for whatever variable name you may have stored the returned strucutre of a call to pertinentItems):
- output[0] is an array of all the found matching elements
- output[1] is an array carrying all the positions of those indexes in the original array
Once you have such data:
-
Get my function named fullRangeCollection at bottom of this file and run it both on the returned output[0] and output[1]. You'd get two symmetrical arrays returned - see documentation for fullRangeCollection).
You'll run fullRangeCollection twice, passing to its two mandatory arguments named array, range the following:
fullRangeCollection(output[0], sequenceArray.length)
fullRangeCollection(output[1], sequenceArray.length)
- You can now do two things: if you want to know all the combinations considering therefore all possible sub sequences, you already have them as indexes stored in fullRangeCollection(output[1], sequenceArray.length) and you have nothing more to do: they are all the index positions in the original input array where such combinations where located (the symmetrical correspondence to the indexes drawn running fullRangeCollection on output[1] is obviously the result drawn when you ran fullRangeCollection onto output[0]).
If on the other hand you want to check only some of these combinations, loop and check fullRangeCollection(output[0], sequenceArray.length) and find the specific matches you're interesetd in; once found you still have all the indexes of such matches as they appear in the original array stored in fullRangeCollection when run on the indexes collection output[1].
- Doing these things above, is the equivalent functionality to achieve your purpose and it doesn't spend more time or coding than a brand new script just for this: the main engine for such a purpose is indeed fullRangeCollection if you run it on the output drawn by pertinentItems().
So no reason to reinvent it.
The looseSubSequences codex now:
The returned output is in its structure absolutely identical to the shape it has in looseSequences except for the obvious fact it would report much more matches. Consequently I won't discuss the output structure again! Refer to the looseSequences explanations on the returned structure as outlined previously in this file.
Since the task is recursive, it can be time consuming on a relatively long list of arrays (altough beware: in the test form it appears comparatively but significantly slower because the testing process has to build also the output text, and assembling growing strings to print at a second time, is a characteristic hassle in javascript).
Undoubtedly you're wondering: what about a strict sub sequences function, Al?
But to my eyes that doesn't make much sense. If a pattern is strict, searching subsequences in a strict range (for the full range option you read the comments above) in it may be pointless. Let's imagine:
[A B C B B C A B B A C]
If you search say for [A B C] you can just use the standard strictSequences for subpatterns are impossible. The only case you can have subpatterns as far as I can see is with thigs like:
[A B A B A B A B] and you're searching for [A B A]
That's just a sequence of palindromes.
Moreover, looseSubSequences detects them (yup!), but along with the other possible combinations (namely: reports BAA and AAB too).
So I'm not so sure we need a whole brand new function only to account for that isolated case.
I'm not yet, at least...
|