|
|
|
|
|
|
|
|
|
PHP APHORISMS: REUSABLE CODE SNIPPETS AND FUNCTIONS. ARRAY COMPARISONS, ARRAY ARGUMENTS UNFOLDING, ARRAY SLICING AND AUTO MERGING, STRING PASSWORD AT LEAST AT MOST X CHARS OR NUMBERS CHECK
|
|
Coding Aphorisms, namely snippets of code whose purpose is that of being reusable. Yet not always their apparent simplicity means that the task was trivial. On the contrary it might have been occasionally daunting for a developer, and yet accomplished here with not too many lines of code.
|
|
September 2005 |
|
{ @ }
|
|
|
|
THE ARRAY COMPARE FUNCTION
|
|
A function that compares two arrays and returns all the differences and identities
|
A Steve Hanks painting
|
This function may appear a simple one, and yet many programmers would have started attempting loops, in order to achieve this goal, rather than using Php built in subroutines.
You pass to it 2 arrays (whether numerically indexed or associative is immaterial). The function will return an associative array thus composed:
- identical: that is, the first index of the returned associative array is exactly this string: 'identical'.
It holds a numerically indexed array whose each entry represents a value that was found in both the passed arrays.
- added: that is, the second index of the returned associative array is exactly this string: 'added'.
It holds a numerically indexed array whose each entry represents a value that was not found in the array passed as first argument but that was present in the second.
- discarded: that is, the third index of the returned associative array is exactly this string: 'discarded'.
It holds a numerically indexed array whose each entry represents a value that was not found in the array passed as second argument but that was present in the first (that is, the viceversa of the above).
No multiple values get returned, that is if there are multiple instances of the same value in any or both the argument arrays, the returned arrays will report them only once (which is arguably what you want).
Example:
compareArrays(
array('a', 'b', 'b', 'c', 'd', 'e', 'f') ,
array('a', 'd', 'e', 'f', 'g', 'h', 'i')
);
That would return as value the following associative array whose each entry holds an array itself:
Array(
['identical'] => Array('a', 'd', 'e', 'f') ,
['added'] => Array('g', 'h', 'i') ,
['discarded'] => Array('b', 'c')
)
This function would work only with arrays that hold either numbers or strings as values, not with arrays that hold other arrays or objects.
This function can be useful when checking data alterations whereas some data was first passed to html forms via php and then returned modified to the server after -arguably- client side or end user driven manipulations on such data.
Nesting this function into a loop so to compare multiple arrays scanned by such loop, might produce several interesting combinations depending on which part of the returned associative array you instruct to be used as one of the arguments at each next iteration of the nesting loop.
THE ARGUMENTS UNFOLDER
|
|
A function that unfolds the arguments passed to the array it is within, and return them into one wholesome array to grant an unique format of the arguments
|
A Steve Hanks painting
|
To an array you can pass arguments basically in three ways:
- As a list of items, namely writing them down consequentially:
foo(1, 2, 3, 4)
- As an array (think of perl whose functions allow only one argument to be passed, exactly in the shape of an array - so that one has to compact in one array whatever list one would have otherwise passed in another programming language):
foo( array(1, 2, 3, 4) )
- Eventually, the arguments could be passed as a mix of both: a few as arrays, a few as list elements, assuming we do not know for sure what will be what:
foo(1, array(2, 3), 4).
This is not inconceivable.
A Joan Miro painting
|
This differentiation mainly resides in the following reason: a human, like a programmer passing the arguments in the source code of a script, is certainly more inclined to pass them as a list.
Yet a machine as a computer, if required to pass such a list, could pass it only compacting it as one single array, and then deliver it to the designed function as its exclusive argument or as an instance of a machine generated argument.
Humans naturally prefer writing lists; but computers naturally don't yield lists, computers naturally yield arrays.
Therefore there can be circumstances where you may want to recover homogeneity in the passed arguments so that to be confident their eventual format is unique and consistent rather than potentially mixed.
This for instance happens when you don't know for sure which arguments will be passed or which bypassed, or when the input flexibility you grant to your functions is such that you can not know for sure in what circumstances your script will be directly edited by an unknown programmer (which could well feed input arguments either as lists or as arrays too, depending on the programmer's habits) or would simply get committed to a machine produced set of input arguments (enough to fill in all the capacity of arguments expected by the signature, or maybe only partial) which as such, and as we said, could only be in the format of array/s.
I used often this unfolding procedure [ for instance here] because such an approach is a good defense against a few unpredicatable errors when passing arguments - typical case a programmer that delivers by mistake an expected list arranged into an array: using this method your script won't flinch: it can remake its expected list out of a mixed input environment.
This function will produce such desired homogeneity granting one format: that of an unidimensional array.
This produced (unfolded) array ranges all the arguments as an unidimensional array, so that among the arguments to unfold those that were items of an array will appear as disengaged from their original array and just lined up with all the others in the newly produced output array.
Your scripts can then afford being internally cognizant only of this one single arguments format out of a promiscuous environment, because they take care of rebuilding this format in case some mistake get into the input way - and maybe it is worth remembering that Php, like Javascript, allows flexible signatures and overloading is not a necessity.
Whatever input policy then the passed arguments have, your script will know it will have them lined up in one single array to loop regardless of how they appeared at first.
You pass to this function three arguments, whereas only the first is mandatory:
- The arguments of the calling function; I now explain.
Since the argumentsUnfolder, in order to work, has to be called from within the function whose arguments must be unfolded, this means that such first argument must be the built in php function:
func_get_args()
Please note that such built in function func_get_args() does not unfold the arguments that it grabs and returns, but places all of them onto the dorsal backbone of an array produced for the purpose - on such "dorsal", any arguments that was an array, is still an array. So they are not unfolded by this php built in method, and rather than simplified we could say they get somewhat complexified.
- An optional start parameter, which must be a number (otherwise defaults to zero).
Such a number will represent the offset of the passed arguments from which the unfolding process has to start.
In this fashion it is possible to accommodate more complex settings like, for instance, those of functions whose first arguments you do not want to touch, but whose arguments starting from a specific offset onward you want to unfold.
- An optional until parameter, which must be a number (otherwise defaults to the first argument array length).
Such a number will represent the offset of the passed arguments at which the unfolding process has to end.
In this fashion it is possible to accommodate more complex settings like, for instance, those of functions whose last arguments you do not want to touch, but whose arguments starting from a specific previous offset you want to unfold.
The function returns a single array, numerically indexed, whose each value will be an argument of the calling function. Thus you have an homogeneous output: a surely unidimensional array out of a potentially mixed environment of lists and arrays.
Please note that this function will unfold only the first level of arguments entries found to be arrays: that is, if an argument is not just an array of values but an array of arrays, only the former will be reported, the held array will not be unfolded but will be returned still as it was - which is arguably exactly what you'd expect such a routine to do!
Anyway if you are interested into complete and powerful irregular matrix inspectors and unfolders, click here for the javascript version and click here for the Php matrix unfolders version.
Now an example:
function foo(){/*intentionally oversimplified calling function:
I just return the unpacked fold, but in a production environment after unpacked
you'd scan your arguments to manipulate them*/
return argumentsUnfolder( func_get_args() );
}
//now call the foo function with a few (mixed) arguments:
foo('a', 'b', array('c', 'd'), 'e', array('f', 'g', 'h'), 'i', 'j');
Such an expression would return a linear flowing array:
array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j')
If you would have specified the other parameters (I now specify both for illustration purposes):
function foo(){
return argumentsUnfolder(func_get_args(), 3, 6);
}
foo('a', 'b', array('c', 'd'), 'e', array('f', 'g', 'h'), 'i', 'j');
Such an expression would return:
array('e', 'f', 'g', 'h', 'i')
Namely would start unfolding from the passed arguments offset index 3, which in our case coincides with the letter 'e', and would proceed only until the passed argument offset index 6 excluded (open end range), which in our example coincides with the letter 'i'.
THE ARRAY AUTO MERGER
|
|
A cute snippet to rearrange arrays
|
A Steve Hanks painting
|
This function extracts slices from an array once provided, along with the input array to manipulate, also a starting offset (and an optional end offset) index(es), and rearranges in various ways the array generated chunks that got split after such offset/s.
The function takes the following arguments:
- An array.
- A number which determines from which offset the slice must be drawn.
If this is the only further argument provided, the function does this: it moves all the entries after such offset before all the entries that were before it:
$input = array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
autoMerger($input, 3);
//returns:
array(3,4,5,6,7,8,9,10,0,1,2)
-
This third argument can be an optional second number, defining if passed the end offset.
-
If and only if the third argument has been passed, this fourth last argument (which must be a number) plays a role:
- It is zero:
it instructs to put the slice between $start and $end at the beginning
$input = array(0,1,2,3,4,5,6,7,8,9,10);
autoMerger($input,3,5, 0)
//returns:
array(3,4,0,1,2,5,6,7,8,9,10)
- It is 1:
it instructs to put the slice between $start and $end at the end
$input = array(0,1,2,3,4,5,6,7,8,9,10);
autoMerger($input,3,5, 1)
//returns:
array(0,1,2,5,6,7,8,9,10,3,4)
- It is 2:
it instructs to swap $start and $end
$input = array(0,1,2,3,4,5,6,7,8,9,10);
autoMerger($input,3,5, 2)
//returns:
array(5,6,7,8,9,10,3,4,0,1,2)
- It is 3:
cumulates #1 and #2:
$input = array(0,1,2,3,4,5,6,7,8,9,10);
autoMerger($input,3,5, 3)
//returns:
array(5,6,7,8,9,10,0,1,2,3,4)
- It is anything else than the above:
cumulates #0 and #2 (actually the same output as without passing the third argument):
$input = array(0,1,2,3,4,5,6,7,8,9,10);
autoMerger($input,3,5, 12037)
//returns:
array(3,4,5,6,7,8,9,10,0,1,2)
The function does not affect the original. If you want it to work with pointers and thus affect the original directly without producing runtime copies, change in the code the line:
function autoMerger($array=array(),
into a pointer, namely prefixing a & to the function's first argument and eliminating the default first argument value; that is:
function autoMerger(&$array,
THE STRING AT LEAST AT MOST VERIFIERS
|
|
Verify whether in a string there are at least, at most, or both at least and at most, either chars or numbers
|
A Steve Hanks painting
|
Actually this is the Php answer to a question once I read on a javascript newsgroup (and for which they even got paid!): checking whether in a string of any length, which was supposed to be a password, there were at least x numbers.
As a matter of fact, this Php could be very easily translated into its equivalent javascript.
This snippet addresses that question and elaborates a few obvious variations on it that might be of some interest as they appear logically entailed.
These are three snippet functions:
-
atLeast()
It takes the following arguments:
- The input string to verify.
- A x number meaning the minimum required amount in the string to pass the test.
- Either number 1 (default) which means we want to run the test for the presence of x numbers into the string, or zero to signify we want to run the test for the presence of x chars into the string.
print atLeast('1s3cr3t', 2, 1); //at least 2 numbers: true
-
atMost()
It takes the following arguments:
- The input string to verify.
- A x number meaning the maximum required amount in the string to pass the test.
- Either number 1 (default) which means we want to run the test for the presence of x numbers into the string, or zero to signify we want to run the test for the presence of x chars into the string.
print atMost('1s3cr3t', 2, 0); //at most 2 chars: false
-
atLeastMost()
It takes the following arguments:
- The input string to verify.
- A x number meaning the minimum required amount in the string to pass the test.
- A x number meaning the maximum required amount in the string to pass the test.
- Either number 1 (default) which means we want to run the test for the presence of x numbers into the string, or zero to signify we want to run the test for the presence of x chars into the string.
print atLeastMost('1s3cr3t', 1, 3, 1 );//at least 1 at most 3 numbers: true
A beautiful Cindy Sherman photo
|
|
|