Created
September 24, 2020 19:01
-
-
Save bennadel/23516c52a935624eeed39afd2ead4125 to your computer and use it in GitHub Desktop.
ArrayPop(), ArrayShift(), And ArraySliceSafe() In Lucee CFML 5.3.6.61
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<cfscript> | |
// NOTE: The concepts of "left" and "right" on an Array mirror the existing concepts | |
// for Strings. Meaning, String.left( 1 ) gets index [ 1 ] on said string. As such, | |
// Array.left( 1 ) will also get index [ 1 ] on said array. | |
dump( arrayLeft( [], 3 ) ); | |
dump( arrayLeft( [ "a" ], 3 ) ); | |
dump( arrayLeft( [ "a", "b", "c", "d", "e", "f" ], 3 ) ); | |
echo( "<br />" ); | |
dump( arrayRight( [], 3 ) ); | |
dump( arrayRight( [ "a" ], 3 ) ); | |
dump( arrayRight( [ "a", "b", "c", "d", "e", "f" ], 3 ) ); | |
echo( "<br />" ); | |
dump( arrayRest( [] ) ); | |
dump( arrayRest( [ "a", "b", "c" ] ) ); | |
// ------------------------------------------------------------------------------- // | |
// ------------------------------------------------------------------------------- // | |
/** | |
* I return the N-LEADING values (at most) in the collection. | |
* | |
* @collection I am the collection being sliced. | |
* @count I am the number of leading values to include in the slice. | |
*/ | |
public array function arrayLeft( | |
required array collection, | |
required numeric count | |
) { | |
return( arraySliceSafe( collection, 1, count ) ); | |
} | |
/** | |
* I return the N-TRAILING values (at most) in the collection. | |
* | |
* @collection I am the collection being sliced. | |
* @count I am the number of trailing values to include in the slice. | |
*/ | |
public array function arrayRight( | |
required array collection, | |
required numeric count | |
) { | |
var startIndex = ( collection.len() - count + 1 ); | |
return( arraySliceSafe( collection, startIndex, count ) ); | |
} | |
/** | |
* I return the N-1 trailing values in the collection. | |
* | |
* @collection I am the collection being sliced. | |
*/ | |
public array function arrayRest( required array collection ) { | |
return( arraySliceSafe( collection, 2 ) ); | |
} | |
/** | |
* I return a SHALLOW copy of the collection. | |
* | |
* @collection I am the collection being copied. | |
*/ | |
public array function arrayCopy( required array collection ) { | |
return( arraySliceSafe( collection ) ); | |
} | |
/** | |
* I perform a .slice() on the given collection, safely handling cases in which the | |
* startIndex or count go beyond the bounds of the collection - only the overlapping | |
* portions of the collection are returned. | |
* | |
* @collection I am the collection being sliced. | |
* @startIndex I am the (1-based) index at which to start slicing. | |
* @count I am the number of values to include in the slice. | |
*/ | |
public array function arraySliceSafe( | |
required array collection, | |
numeric startIndex = 1, | |
numeric count = collection.len() | |
) { | |
var collectionLength = collection.len(); | |
// NOTE: The endIndex in this case is INCLUSIVE - meaning, it is the last of the | |
// indices to be included in the resultant slice of values. | |
var endIndex = ( startIndex + count - 1 ); | |
// If the given slice-range doesn't overlap with any of the indices in the given | |
// collection, then just return an empty array since no values will be sliced. | |
if ( | |
! collectionLength || | |
( count < 1 ) || | |
( endIndex < 1 ) || | |
( startIndex > collectionLength ) | |
) { | |
return( [] ); | |
} | |
// Clamp the slice-range down to the overlapping portion of the collection. | |
var safeStartIndex = max( 1, startIndex ); | |
var safeEndIndex = min( collectionLength, endIndex ); | |
var safeCount = ( safeEndIndex - safeStartIndex + 1 ); | |
return( collection.slice( safeStartIndex, safeCount ) ); | |
} | |
</cfscript> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<cfscript> | |
values = [ "a", "b", "c", "d" ]; | |
while ( values.len() ) { | |
dump( arrayShift( values ) ); | |
} | |
echo( "<br />" ); | |
values = [ "a", "b", "c", "d" ]; | |
while ( values.len() ) { | |
dump( arrayPop( values ) ); | |
} | |
// ------------------------------------------------------------------------------- // | |
// ------------------------------------------------------------------------------- // | |
/** | |
* I remove the first item from the collection and return it. This MUTATES the given | |
* collection. | |
* | |
* @collection I am the collection being mutated. | |
*/ | |
public any function arrayShift( required array collection ) { | |
return( arrayTakeAt( collection, 1 ) ); | |
} | |
/** | |
* I remove the last item from the collection and return it. This MUTATES the given | |
* collection. | |
* | |
* @collection I am the collection being mutated. | |
*/ | |
public any function arrayPop( required array collection ) { | |
return( arrayTakeAt( collection, collection.len() ) ); | |
} | |
/** | |
* I remove and return the value at the given collection index. This MUTATES the given | |
* collection. | |
* | |
* @collection I am the collection being mutated. | |
* @targetIndex I am the index of the value being removed. | |
*/ | |
public any function arrayTakeAt( | |
required array collection, | |
required numeric targetIndex | |
) { | |
if ( ! collection.indexExists( targetIndex ) ) { | |
throw( | |
type = "IndexOutOfBounds", | |
message = "Target index is not defined.", | |
detail = "arrayTakeAt() requires the index (#targetIndex#) to be defined." | |
); | |
} | |
var value = collection[ targetIndex ]; | |
collection.deleteAt( targetIndex ); | |
return( value ); | |
} | |
</cfscript> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment