SCRIPTING:

Angela Lindvall by Mert Alas and Marcus Piggott
MISCELLANEOUS FUNCTIONS #5: ALL CAPITALIZATIONS IN A STRING. ARRAY: ALL KEY/VALUE SWAPPERS

I include here a few miscellaneous functions: from two arrays make an array whose keys are the values drawn from the first array and whose values are drawn from the second array (equivalent of PHP array_combine) and more likewise combinations; swap an array keys with its values.

Capitalize the first letters in each word of a string, or lowercase them. Include or Exclude exceptions. Capitalize only specific words.

January 2004
{ @ }

The model above is Angela Lindvall
photo by Mert Alas and Marcus Piggott
LOADS OF ANGELA LINDVALL ON THE NET
A file with a dedication: to Pia Muran de Assereto, who likes Ophelia by John Everett Millais.


MISCELLANEOUS ARRAY FUNCTIONS
A few functions for various purposes

A Cindy Sherman artwork
A Cindy Sherman artwork
In this file we deal with two sets of functions, the one to manipulate arrays, the other to manipulate strings.

I'll describe first what types of array manipulations I do here and I will include the relative test form, then in the next section what type of string manipulation it's performed with the other functions and their relative test forms.
Though this website has test forms for every function and nearly in every file, in this case they may be even more useful than in all the other cases, in order to see at a glance what each function does (for which, occasionally, the written description may be less obvious than seeing the apparent result).

The former set has been devised after having noticed the new PHP 5 function array_combine.
That Php function takes in two arguments, both arrays, and returns one array whose each key is a value drawn from the first array and whose values are the values drawn from the second array.

It was immediately apparent to my eyes a twofold issue:
  • There are more possible combinations, namely:

    • Assign to the new array's keys the values of the first array and as the new array's values the values of the second array (proper PHP 5 array_combine emulation).

      The name of this javascript function that performs the above is combiner and this function takes in two arguments, namely the two arrays to be "combined":
      var newArray=arrayCombine(array1, array2);
    • Assign to the new array's keys the keys of the first array and as the new array's values the values of the second array.

      The name of this javascript function that performs the above is combiner2 and this function takes in two arguments, namely the two arrays to be "combined":
      var newArray=arrayCombine2(array1, array2);
    • Assign to the new array's keys the values of the first array and as the new array's values the keys of the second array.

      The name of this javascript function that performs the above is combiner3 and this function takes in two arguments, namely the two arrays to be "combined":
      var newArray=arrayCombine3(array1, array2);
    • Assign to the new array's keys the keys of the first array and as the new array's values the keys of the second array.

      The name of this javascript function that performs the above is combiner4 and this function takes in two arguments, namely the two arrays to be "combined":
      var newArray=arrayCombine4(array1, array2);
  • The PHP 5 array_combine method has an "issue": if the passed two arrays are not of the same length, an error is returned.
    Thus it was possible to make a more flexible approach, which relied onto at least three possibilities:

    • As soon as the size limit of the second array is surpassed, restart looping it from the beginning. This is the behaviour I implement here.
      The functions anyway are a good draft that by merely changing one line can be lent to either of the following two solutions:

    • As soon as the size limit of the second array is surpassed, go on assigning always one of its values (the last one? The first one? An X one?).

      In the codes you will find a line saying:
      valuesValues.push(v);//*or: if(typeof(v)=="undefined"){break? v=something?}*/
      To implement this variation change that whole line into:
      if(typeof(v)=="undefined"){v=values[0];}
      If you want, change zero with an index you find suitable, but within the limits of the second array (so, arguably, either 0 or its length-1).

    • As soon as the size limit of the second array is surpassed, go on assigning a default value defined elsewhere than in this second array.

      In the codes you will find a line saying:
      valuesValues.push(v);//*or: if(typeof(v)=="undefined"){break? v=something?}*/
      To implement this variation change that whole line into:
      if(typeof(v)=="undefined"){v="something";}
      Change "something" with whatever you find suitable.
A William Trost Richards painting
A William Trost Richards painting
In the codes I was forced to loop the second passed argument - though this loop is made only once, and is not nested in another loop.
This happens because given the type of tasks, it is well possible the passed arrays are associative arrays, namely indexed by literals rather than by numbers: as such they could not be addressed by a numerical progressive index and so to grasp its values and keys it was necessary to loop it and assign all the keys and all the values to two different arrays built up within the functions's scope.
This was necessary because in Javascript, unlike in PHP, methods designed to shift and to push onto arrays would not work on associative array, sadly.

There is then another function named arraySwap.
This function takes in one argument only, an array, and produces out of it a new array whose values and keys are swapped.
An entirely optional second argument, if passed, would assign as values of the newly produced array always such passed argument - maybe not very useful, but since I was doing this type of stuff, it was a "feature" added with a minimal effort: as my programming "philosophy" always goes, better one option more than one less, you're still on time to remove from the draft the ones you need not at a second time rather than having to think hard so to implement them from scratch.
A third argument, still optional, affects the behaviour in case you have passed the second: passing the third, the newly produced array will have as its index the keys rather than the values of the input array (arguably, even less useful).

All the functions described above presume that, in the two arrays passed as arguments (or in the only one dealt with by arraySwap) all the values and all the keys in both arrays are unique and have no duplicates.

If a duplicate would be present, upon reassigning it as a key (like in arrayCombine where you reassign as keys of array1 its very same values, which might well carry duplicates) would immediately overwrite any possible previously defined key that carried that same identifier.
That is, whereas in an array values can be duplicated, yet the keys of an array must be unique (in fact this is why they are so often referred to as keys: for they are fit for and meant to identifiy one "gate" only) and thus, if a key duplicate is met upon assigning it to the pool of keys already present in an array, the last arrived key overwrites the previous one(s): there will not be two identical keys in the array, though there can be more duplicated values yet held by different keys:
array[0]="hi";
array[2]="hi";
this can be: two identical values but on two different keys

But it could not be viceversa: if
array[0]="hi"
exists and later arrives
array[0]="hello"
Ther result will be one and only one (and not two!)
array[0]
entry, and it will be the last one arrived namely the one carrying the value "hello" that will overwrite any previous instance of... itself.

Though I won't let you play with the following in the test form, yet I am to provide you with a set of functions that are equivalent to the previous ones and that yet can accommodate these cases, namely duplicates.
The codes of these functions are in the textarea that carries all of the array combiner codes, though they are not included within the set of functions you can trigger in the test form.
These new functions are named as follows:
  • arrayCombineX is the same as arrayCombine but accommodates duplicates.
  • arrayCombineX2 is the same as arrayCombine2 but accommodates duplicates.
  • arrayCombineX3 is the same as arrayCombine3 but accommodates duplicates.
  • arrayCombineX4 is the same as arrayCombine4 but accommodates duplicates.
  • arraySwapX is the same as arraySwap but accommodates duplicates.
The way this gets achieved is the following one: return an array whose each entry is always an array itself of at least one entry (for single matches) or of multiple entries (for duplicated matches).

This I deem the only "bullet proof" way to handle these situations - and for various considerations, especially when keeping in mind that whereas PHP allows only String or Number data types to perform as keys of an array, Javascript allows everything included even Objects.
And if you consider that an assigned value could be an array originally (an array can well have as its values other arrays, or Objects!), then checking whether the typeof of an entry is an array data type with the idea of veryifing whether it included more matches or not, is no longer a safe way to check that case: so all of the entries must be arrays, and these latter can then safely hold all the rest, included other arrays if they were met in the arrays passed as arguments.

So the "bullet proof" method is the mentioned one: the returned recombined array is an array whose keys are unique, but the values held are always an array themselves and of at least one entry: one entry alone if there was no duplicate, or more than one entries if it had to accommodate duplicates.

Example: you have two arrays like:
array1=[0,1,2,3,4,5];
array2=[0,1,1,1,2,7];

If you want to use the values of array2 (which carries three duplicated number 1) as keys in the newly recombined array, and the values of array1 as the newly recombined array values, you'd get a structure as follows (pseudo javascript code):
result[0]=array(0);
result[1]=array(1,2,3);
result[2]=array(4);
result[7]=array(5);

such would be the result of a call like:
var result = arrayCombineX( array2, array1 );
Note: please keep in mind that javascript may produce apparent empty slots if the keys are numbers and there are gaps between the sequence of such keys (such as 7, then 12: 4 numbers missing namely 8, 9, 10, 11) - an interesting answer about this javascript behaviour by Mr. Danny Goodman can be located clicking here.
Therefore in the returned arrays of the X versions, there always exists at least a:
result[index][0]
entry, and then there could be, beyond that, more subsequent entries to host the possible duplicates such as like:
result[index][0+num]

So when dealing with the returned outcome of the X versions of these functions: check the length!
if(result[index].length==1){/*no duplicates*/}
else{/*duplicates present!*/}

Here are your codes, and after them the test form to check all the functionalities of these array combiner functions.
To make things simpler (after all the test form is just an example to get acquainted with what the functions do) the two input arrays are built up with no more than 5 entries, and the second array is shorter than the first one. Though the test form provides you ways to edit both the keys and the values of both arrays, I suggest to you not to do it if you are not relatively expert.
A Cindy Sherman artwork
A Cindy Sherman artwork

All The Combiners Codes

The Combiners Test Form
ARRAY 1 KEYS:
Allow editing field above? (at your "risk")
ARRAY 1 VALUES:
Allow editing field above? (at your "risk")
ARRAY 2 KEYS:
Allow editing field above? (at your "risk")
ARRAY2 VALUES:
Allow editing field above? (at your "risk")
Pick Your Combiner:
arrayCombine(array1, array2):  
arrayCombine2(array1, array2):
arrayCombiner3(array1, array2):
arrayCombine4(array1, array2):
arraySwap(array1): overwrite with "1" keep key
RESULTS:
A John Everett Millais painting
A John Everett Millais painting


MISCELLANEOUS STRING FUNCTIONS
A few functions for various purposes

A Paul Delaroche painting
A Paul Delaroche painting
The second lot of functions is meant to arrange by javascript the capitalization of the first char in each word of a string.
The flexibility that these functions allow is that not only you could lowercase rather than uppercase (default behaviour), but that you can also set particular chars, or also whole words, that you want to make exceptions out of them both in the sense they should not be affected or in the sense they must be the only ones affected.

The functions are these, and I describe their arguments:

  • capitalizer
    It takes in the following arguments:
    • string: the input string.
    • limit: optional number: if passed after having performed the specified amount of string modifications, the function would perform no other though more words fit to capitalize could be present.
    • excludedCharsAssociativeArray: optional; if not passed, all the first chars in every word get capitalized; if passed, it must be an associative array of chars that you do not want to capitalize if met at the beginning of a word (that is, they are exceptions).
      Since this array must be associative, namely the chars to exclude must be the keys and not the values of such array, you may want to consider making first a default array with your chars to exclude, and then turn it into an associative one by using the arraySwap function earlier documented, and pass this latter result to the function; example:
      var excluded=new Array("a", "b");

      var output=capitalizer(
      "cc bb aa dd",
      0,
      arraySwap(excluded)
      );
      //that would print: Cc bb aa Dd
    • lowerCase: if passed, it lowercases rather than capitalize!

  • capitalizer2
    It takes in the following arguments:
    • string: the input string.
    • limit: optional number: if passed after having performed the specified amount of string modifications, the function would perform no other though more words fit to capitalize could be present.
    • includedCharsAssociativeArray: an associative array: only and exclusively the chars passed in this array and found at the beginning of a word would be capitalized. If it is empty or non present, nothing gets capitalized.
      To produce this associative array, you may want to check again the same procedure explained to produce the excludedCharsAssociativeArray
    • lowerCase: if passed, it lowercases rather than capitalize!
      Do remember that if you want this to work correctly on this specific function, the chars passed in the includedCharsAssociativeArray argument should be uppercase, for the argument means to spot them (from uppercase make lowercase, right?), and whereas the previous function would work as well (that is, for both lower and upper case instances) at excluding them and for technicalities I won't bother to explain here, the same does not apply with this function when at including them.

  • capitalizer3
    It capitalizes chars (and even whole words if required) but with much more powerful options, see the arguments and then do use the test form:
    • string: the input string.
    • substringsArray: a standard (that is, not an associative one) array. Only the words listed here get their first char capitalized, or get modified. Remember: only words or chars listed here.
    • fullWordBounds: if passed, only the exact matches of substringsArray are modified (say: YOU changes exact matches as YOU but not as, say, YOURSELF; H changes an isolated H but not HALLO), whereas otherwise only words starting with those chars are changed (YOU changes YOU and YOUrself, for instance).
    • fullCapitalize: if passed and no fullWordBound argument is passed, it capitalizes whole words and also char matches in between words. If fullWordBound argument is passed, it fully capitalizes only whole words that fully match with the passed ones.

      Next arguments, not really important:

    • regExpIsCaseSensitive: optional. By default the words passed as the substringsArray argument are all considered case sensitive. To change this, pass this argument as 1.
    • lowerCase: if passed, it lowercases rather than capitalize.
A Tom Wesselmann painting
A Tom Wesselmann painting

All The Capitalizer Codes

The Capitalizers Test Form
The Capitalizer
Input String:
limit:
Associative Array (separate items by a white space)
Lowercase?
RESULTS:

The Capitalizer2
Input String:
limit:
Associative Array (separate items by a white space)
Lowercase?
RESULTS:

The Capitalizer3
Input String:
Array (separate items by a white space)
Full Capitalize?


Full Word Bound?
regExpIsCaseSensitive?
Lowercase?
RESULTS:

An Atkinson Grimshaw painting
An Atkinson Grimshaw painting