1  
     2  /**
     3   * com.sekati.utils.ArrayUtils
     4   * @version 1.2.1
     5   * @author jason m horwitz | sekati.com
     6   * Copyright (C) 2007  jason m horwitz, Sekat LLC. All Rights Reserved.
     7   * Released under the MIT License: http://www.opensource.org/licenses/mit-license.php
     8   */
     9   
    10  /**
    11   * Static class wrapping various Array utilities.
    12   */
    13  class com.sekati.utils.ArrayUtils {
    14  
    15  	/**
    16  	 * insert an element into array at a specific index
    17  	 * @param a (Array)
    18  	 * @param objElement (Object)
    19  	 * @param nIndex (Number)
    20  	 * @return Array
    21  	 */
    22  	public static function insert(a:Array, objElement:Object, nIndex:Number):Array {
    23  		var aA:Array = a.slice( 0, nIndex - 1 );
    24  		var aB:Array = a.slice( nIndex, a.length - 1 );
    25  		aA.push( objElement );
    26  		return ArrayUtils.merge( aA, aB );
    27  	}
    28  
    29  	/**
    30  	 * remove all instances of an element from an array
    31  	 * @param a (Array)
    32  	 * @param objElement (Object)
    33  	 * @return Array
    34  	 */
    35  	public static function remove(a:Array, objElement:Object):Array {
    36  		for(var i:Number = 0; i < a.length ; i++) {
    37  			if (a[i] === objElement) {
    38  				a.splice( i, 1 );
    39  			}
    40  		}
    41  		return a;
    42  	}
    43  
    44  	/**
    45  	 * search an array for a given element and return its index or null
    46  	 * @param a (Array)
    47  	 * @param objElement (Object)
    48  	 * @return Number
    49  	 */	
    50  	public static function search(a:Array, objElement:Object):Number {
    51  		for (var i:Number = 0; i < a.length ; i++) {
    52  			if (a[i] === objElement) {
    53  				return i;
    54  			}
    55  		}
    56  		return null;
    57  	}
    58  
    59  	/**
    60  	 * shuffle array items
    61  	 * @param a (Array)
    62  	 * @return Void
    63  	 */
    64  	public static function shuffle(a:Array):Void {
    65  		for (var i:Number = 0; i < a.length ; i++) {
    66  			var tmp:Object = a[i];
    67  			var randomNum:Number = random( a.length );
    68  			a[i] = a[randomNum];
    69  			a[randomNum] = tmp;
    70  		}
    71  	}
    72  
    73  	/**
    74  	 * return a clone of the array
    75  	 * @param a (Array)
    76  	 * @return Array
    77  	 */
    78  	public static function clone(a:Array):Array {
    79  		return a.concat( );
    80  	}
    81  
    82  	/**
    83  	 * merge two arrays into one
    84  	 * @param aA (Array)
    85  	 * @param aB (Array)
    86  	 * @return Array
    87  	 */
    88  	public static function merge(aA:Array, aB:Array):Array {
    89  		var aC:Array = ArrayUtils.clone( aB );
    90  		for(var i:Number = aA.length - 1; i > -1 ; i--) {
    91  			aC.unshift( aA[i] );
    92  		}
    93  		return aC;
    94  	}	
    95  
    96  	// Swaps two elements at the given indexes of the subject array.
    97  	/**
    98  	 * Swap two elements positions in an array
    99  	 * @param a (Array)
   100  	 * @param nA (Number) element A's index
   101  	 * @param nB (Number) element B's index
   102  	 * @return Array
   103  	 * @throws Error on invalid array index
   104  	 */
   105  	public static function swap(a:Array, nA:Number, nB:Number):Array {
   106  		if (nA >= a.length || nA < 0) {
   107  			throw new Error( "@@@ com.sekati.utils.ArrayUtils.swap() Error: Index 'A' (" + nA + ") is not a valid index in the array '" + a.toString( ) + "'." );
   108  			return a;
   109  		}
   110  		if(nB >= a.length || nB < 0) {
   111  			throw new Error( "@@@ com.sekati.utils.ArrayUtils.swap() Error: Index 'A' (" + nB + ") is not a valid index in the array '" + a.toString( ) + "'." );
   112  			return a;
   113  		}
   114  		var objElement:Object = a[nA];
   115  		a[nA] = a[nB];
   116  		a[nB] = objElement;
   117  		return a;
   118  	}	
   119  
   120  	/**
   121  	 * Return alphabetically sorted array.
   122  	 * @param a (Array)
   123  	 * @return Array
   124  	 */
   125  	public static function asort(a:Array):Array {
   126  		var aFn:Function = function (element1:String, element2:String):Boolean {
   127  			return element1.toUpperCase( ) > element2.toUpperCase( );
   128  		};
   129  		return a.sort( aFn );
   130  	}
   131  
   132  	/**
   133  	 * return array with duplicate entries removed
   134  	 * @param a (Array)
   135  	 * @return Array
   136  	 */
   137  	public static function removeDuplicate(a:Array):Array {
   138  		a.sort( );
   139  		var o:Array = new Array( );
   140  		for (var i:Number = 0; i < a.length ; i++) {
   141  			if (a[i] != a[i + 1]) {
   142  				o.push( a[i] );
   143  			}
   144  		}
   145  		return o;
   146  	}
   147  
   148  	/**
   149  	 * compare two arrays for a matching value
   150  	 * @param aA (Array)
   151  	 * @param aB (Array)	
   152  	 * @return Boolean
   153  	 */	
   154  	public static function matchValues(aA:Array, aB:Array):Boolean {
   155  		for (var f:Number = 0; f < aA.length ; f++) {
   156  			for (var l:Number = 0; l < aB.length ; l++) {
   157  				if (aB[l].toLowerCase( ) === aA[f].toLowerCase( )) {
   158  					return true;
   159  				}
   160  			}
   161  		}
   162  		return false;
   163  	}
   164  
   165  	/**
   166  	 * compare two arrays to see if they are identical
   167  	 * @param aA (Array)
   168  	 * @param aB (Array)
   169  	 * @return Boolean
   170  	 */
   171  	public static function compare(aA:Array, aB:Array):Boolean {
   172  		if(aA.length != aB.length) {
   173  			return false;
   174  		}
   175  		for(var i:Number = 0; i < aA.length ; i++) {
   176  			if(aA[i] !== aB[i]) {
   177  				return false;
   178  			}
   179  		}
   180  		return true;
   181  	}
   182  
   183  	/**
   184  	 * Search for a specific value of a property in an array of objects
   185  	 * @param objArr (Array) array of objects
   186  	 * @param prop (String) property to search
   187  	 * @param val (Object) value to locate
   188  	 * @param isCaseInsensitive (Boolean) - define whether prop and val should be case-insensitive [default: false]
   189  	 * @return Object - that matches property value
   190  	 */
   191  	public static function locatePropVal(objArr:Array, prop:String, val:Object, isCaseInsensitive:Boolean):Object {
   192  		for(var o in objArr) {
   193  			if (!isCaseInsensitive) {
   194  				if (objArr[o][prop] == val) return objArr[o];
   195  			} else {
   196  				if (objArr[o][prop].toUpperCase( ) == val.toUpperCase( )) return objArr[o];	
   197  			}		
   198  		}
   199  		return undefined;
   200  	}	
   201  
   202  	/**
   203  	 * Search for a unique value property match and return its index in the array.
   204  	 * @param a (Array) array of objects
   205  	 * @param prop (String) property to search
   206  	 * @param val (Object) value to locate
   207  	 * @return Number - index of hit
   208  	 */
   209  	public static function locatePropValIndex(a:Array, prop:String, val:Object):Number {
   210  		for (var i:Number = 0; i < a.length ; i++) {
   211  			if(a[i][prop] == val) {
   212  				return i;	
   213  			}
   214  		}	
   215  	}
   216  
   217  	/**
   218  	 * Return a new array sliced from original array based on a value property match
   219  	 * @param objArr (Array) array of objects
   220  	 * @param prop (String) property to search
   221  	 * @param val (Object) value to locate
   222  	 * @param isCaseInsensitive (Boolean) - define whether prop and val should be case-insensitive [default: false]
   223  	 * @return Array - array of objects that matches property value
   224  	 */
   225  	public static function sliceByPropVal(objArr:Array, prop:String, val:Object, isCaseInsensitive:Boolean):Array {
   226  		var a:Array = new Array( );
   227  		for(var o in objArr) {
   228  			if (!isCaseInsensitive) {
   229  				if (objArr[o][prop] == val) a.push( objArr[o] );
   230  			} else {
   231  				if (objArr[o][prop].toUpperCase( ) == val.toUpperCase( )) a.push( objArr[o] );	
   232  			}
   233  		}
   234  		return a;	
   235  	}	
   236  
   237  	/**
   238  	 * Return the index of the minimum value in a numeric array
   239  	 * @param a (Array)
   240  	 * @return Number - minimum value
   241  	 */
   242  	public static function min(a:Array):Number {
   243  		var i:Number = a.length;
   244  		var min:Number = a[0];
   245  		var idx:Number = 0;
   246  		while (i-- > 1) {
   247  			if(a[i] < min) min = a[idx = i];
   248  		}
   249  		return idx;
   250  	}
   251  
   252  	/**
   253  	 * Return the index of the maximum value in a numeric array
   254  	 * @param a (Array)
   255  	 * @return Number - maximum value
   256  	 */	
   257  	public static function max(a:Array):Number {
   258  		var i:Number = a.length;
   259  		var max:Number = a[0];
   260  		var idx:Number = 0;	
   261  		while(i-- > 1) {
   262  			if(a[i] > max) max = a[idx = i];
   263  		}
   264  		return idx;	
   265  	}
   266  
   267  	/**
   268  	 * Return the minimum value in a numeric array
   269  	 * @param a (Array)
   270  	 * @return Number - minimum value (0 is returned with 0 length array)
   271  	 */	
   272  	public static function minVal(a:Array):Number {
   273  		return ((a.length <= 0) ? 0 : a[ArrayUtils.max( a )]);
   274  	}
   275  
   276  	/**
   277  	 * Return the maximum value in a numeric array
   278  	 * @param a (Array)
   279  	 * @return Number - maximum value
   280  	 */	
   281  	public static function maxVal(a:Array):Number {
   282  		return ((a[ArrayUtils.max( a )] < 0) ? 0 : a[ArrayUtils.max( a )]);
   283  	}
   284  
   285  	private function ArrayUtils() {
   286  	}
   287  }