9ce195b99d
Match the coding style already present in file (use ii for loop counter..) git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4991 542714f4-19e9-0310-aa3c-eee0fc999fb1
223 lines
7.1 KiB
ActionScript
223 lines
7.1 KiB
ActionScript
//
|
|
// $Id$
|
|
//
|
|
// Narya library - tools for developing networked games
|
|
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
|
|
// http://www.threerings.net/code/narya/
|
|
//
|
|
// This library is free software; you can redistribute it and/or modify it
|
|
// under the terms of the GNU Lesser General Public License as published
|
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This library is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
// Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
// License along with this library; if not, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
package com.threerings.util {
|
|
|
|
/**
|
|
* Contains methods that should be in Array, but aren't. Additionally
|
|
* contains methods that understand the interfaces in this package.
|
|
* So, for example, removeFirst() understands Equalable and will remove
|
|
* an element that is equals() to the specified element, rather than just
|
|
* === (strictly equals) to the specified element.
|
|
*/
|
|
public class ArrayUtil
|
|
{
|
|
/**
|
|
* Creates a shallow copy of the array.
|
|
*
|
|
* @internal TODO: add support for copy ranges and deep copies?
|
|
*/
|
|
public static function copyOf (arr :Array) :Array
|
|
{
|
|
return arr.slice();
|
|
}
|
|
|
|
/**
|
|
* Sort the specified array according to natural order- all elements
|
|
* must implement Comparable or be null.
|
|
*/
|
|
public static function sort (arr :Array) :void
|
|
{
|
|
arr.sort(Comparators.COMPARABLE);
|
|
}
|
|
|
|
/**
|
|
* Perform a stable sort on the specified array.
|
|
* @param comp a function that takes two objects in the array and returns -1 if the first
|
|
* object should appear before the second in the container, 1 if it should appear after,
|
|
* and 0 if the order does not matter. If omitted, Comparators.COMPARABLE is used and
|
|
* the array elements should be Comparable objects.
|
|
*/
|
|
public static function stableSort (arr :Array, comp :Function = null) :void
|
|
{
|
|
if (comp == null) {
|
|
comp = Comparators.COMPARABLE;
|
|
}
|
|
// insertion sort implementation
|
|
var nn :int = arr.length;
|
|
for (var ii :int = 1; ii < nn; ii++) {
|
|
var val :* = arr[ii];
|
|
var jj :int = ii - 1;
|
|
for (; jj >= 0; jj--) {
|
|
var compVal :* = arr[jj];
|
|
if (comp(val, compVal) < 0) {
|
|
break;
|
|
}
|
|
arr[jj + 1] = compVal;
|
|
}
|
|
arr[jj + 1] = val;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Randomly shuffle the elements in the specified array.
|
|
*
|
|
* @param rando a random number generator to use, or null if you don't care.
|
|
*/
|
|
public static function shuffle (arr :Array, rando :Random = null) :void
|
|
{
|
|
var randFunc :Function = (rando != null) ? rando.nextInt :
|
|
function (n :int) :int {
|
|
return int(Math.random() * n);
|
|
};
|
|
// starting from the end of the list, repeatedly swap the element in
|
|
// question with a random element previous to it up to and including
|
|
// itself
|
|
for (var ii :int = arr.length - 1; ii > 0; ii--) {
|
|
var idx :int = randFunc(ii + 1);
|
|
var tmp :Object = arr[idx];
|
|
arr[idx] = arr[ii];
|
|
arr[ii] = tmp;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the index of the first item in the array for which the predicate function
|
|
* returns true, or -1 if no such item was found. The predicate function should be of type:
|
|
* function (element :*) :Boolean { }
|
|
*
|
|
* @return the zero-based index of the matching element, or -1 if none found.
|
|
*/
|
|
public static function indexIf (arr :Array, predicate :Function) :int
|
|
{
|
|
if (arr != null) {
|
|
for (var ii :int = 0; ii < arr.length; ii++) {
|
|
if (predicate(arr[ii])) {
|
|
return ii;
|
|
}
|
|
}
|
|
}
|
|
return -1; // never found
|
|
}
|
|
|
|
/**
|
|
* Returns the first index of the supplied element in the array. Note that if the element
|
|
* implements Equalable, an element that is equals() will have its index returned, instead
|
|
* of requiring the search element to be === (strictly equal) to an element in the array
|
|
* like Array.indexOf().
|
|
*
|
|
* @return the zero-based index of the matching element, or -1 if none found.
|
|
*/
|
|
public static function indexOf (arr :Array, element :Object) :int
|
|
{
|
|
if (arr != null) {
|
|
for (var ii :int = 0; ii < arr.length; ii++) {
|
|
if (Util.equals(arr[ii], element)) {
|
|
return ii;
|
|
}
|
|
}
|
|
}
|
|
return -1; // never found
|
|
}
|
|
|
|
/**
|
|
* @return true if the specified element, or one that is Equalable.equals() to it, is
|
|
* contained in the array.
|
|
*/
|
|
public static function contains (arr :Array, element :Object) :Boolean
|
|
{
|
|
return (indexOf(arr, element) != -1);
|
|
}
|
|
|
|
/**
|
|
* Remove the first instance of the specified element from the array.
|
|
*
|
|
* @return true if an element was removed, false otherwise.
|
|
*/
|
|
public static function removeFirst (arr :Array, element :Object) :Boolean
|
|
{
|
|
return removeImpl(arr, element, true);
|
|
}
|
|
|
|
/**
|
|
* Remove the last instance of the specified element from the array.
|
|
*
|
|
* @return true if an element was removed, false otherwise.
|
|
*/
|
|
public static function removeLast (arr :Array, element :Object) :Boolean
|
|
{
|
|
arr.reverse();
|
|
var removed :Boolean = removeFirst(arr, element);
|
|
arr.reverse();
|
|
return removed;
|
|
}
|
|
|
|
/**
|
|
* Removes all instances of the specified element from the array.
|
|
*
|
|
* @return true if at least one element was removed, false otherwise.
|
|
*/
|
|
public static function removeAll (arr :Array, element :Object) :Boolean
|
|
{
|
|
return removeImpl(arr, element, false);
|
|
}
|
|
|
|
/**
|
|
* Do the two arrays contain elements that are all equals()?
|
|
*/
|
|
public static function equals (ar1 :Array, ar2 :Array) :Boolean
|
|
{
|
|
if (ar1 === ar2) {
|
|
return true;
|
|
|
|
} else if (ar1 == null || ar2 == null || ar1.length != ar2.length) {
|
|
return false;
|
|
}
|
|
|
|
for (var jj :int = 0; jj < ar1.length; jj++) {
|
|
if (!Util.equals(ar1[jj], ar2[jj])) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Implementation of remove methods.
|
|
*/
|
|
private static function removeImpl (
|
|
arr :Array, element :Object, firstOnly :Boolean) :Boolean
|
|
{
|
|
var removed :Boolean = false;
|
|
for (var ii :int = 0; ii < arr.length; ii++) {
|
|
if (Util.equals(arr[ii], element)) {
|
|
arr.splice(ii--, 1);
|
|
if (firstOnly) {
|
|
return true;
|
|
}
|
|
removed = true;
|
|
}
|
|
}
|
|
return removed;
|
|
}
|
|
}
|
|
}
|