Procházet zdrojové kódy

Array.indexOf/lastIndexOf (closes #1242)

Dan Korostelev před 11 roky
rodič
revize
75954e41b9

+ 30 - 0
std/Array.hx

@@ -220,6 +220,36 @@ extern class Array<T> {
 	**/
 	function remove( x : T ) : Bool;
 
+	/**
+		Returns position of the first occurense of `x` in `this` Array, searching front to back.
+
+		If `x` is found by checking standard equality, the function returns its index.
+
+		If `x` is not found, the function returns -1.
+
+		If `fromIndex` is specified, it will be used as the starting index to search from,
+		otherwise search starts with zero index. If it is negative, it will be taken as the
+		offset from the end of `this` Array to compute the starting index. If given or computed
+		starting index is less than 0, the whole array will be searched, if it is greater than
+		or equal to the length of `this` Array, the function returns -1.
+	**/
+	function indexOf( x : T, ?fromIndex:Int ) : Int;
+
+	/**
+		Returns position of the last occurense of `x` in `this` Array, searching back to front.
+
+		If `x` is found by checking standard equality, the function returns its index.
+
+		If `x` is not found, the function returns -1.
+
+		If `fromIndex` is specified, it will be used as the starting index to search from,
+		otherwise search starts with the last element index. If it is negative, it will be
+		taken as the offset from the end of `this` Array to compute the starting index. If
+		given or computed starting index is greater than or equal to the length of `this` Array,
+		the whole array will be searched, if it is less than 0, the function returns -1.
+	**/
+	function lastIndexOf( x : T, ?fromIndex:Int ) : Int;
+
 	/**
 		Returns a shallow copy of `this` Array.
 

+ 26 - 0
std/cs/_std/Array.hx

@@ -84,6 +84,32 @@ import cs.NativeArray;
 		this.length = len;
 	}
 
+	public function indexOf( x : T, ?fromIndex:Int ) : Int
+	{
+		var len = length, i:Int = (fromIndex == null) ? 0 : fromIndex;
+		if (i < 0)
+		{
+			i += len;
+			if (i < 0) i = 0;
+		}
+		return cs.system.Array._IndexOf(__a, x, i, len - i);
+	}
+
+	public function lastIndexOf( x : T, ?fromIndex:Int ) : Int
+	{
+		var len = length, i:Int = (fromIndex == null) ? len - 1 : fromIndex;
+		if (i >= len)
+		{
+			i = len - 1;
+		}
+		else if (i < 0)
+		{
+			i += len;
+			if (i < 0) return -1;
+		}
+		return cs.system.Array.LastIndexOf(__a, x, i, i + 1);
+	}
+
 	public function join( sep : String ) : String
 	{
 		var buf = new StringBuf();

+ 28 - 0
std/flash8/Boot.hx

@@ -239,6 +239,34 @@ class Boot {
 				}
 				return false;
 			}
+			Array.prototype["indexOf"] = function(x, ?fromIndex) {
+				var len = __this__["length"], i = (fromIndex == null) ? 0 : fromIndex;
+				if (i < 0) {
+					i += len;
+					if (i < 0) i = 0;
+				}
+				while (i < len)
+				{
+					if (__this__[i] == x)
+						return i;
+					i++;
+				}
+				return -1;
+			}
+			Array.prototype["lastIndexOf"] = function(x, ?fromIndex) {
+				var len = __this__["length"], i = (fromIndex == null) ? len - 1 : fromIndex;
+				if (i >= len)
+					i = len - 1;
+				else if (i < 0)
+					i += len;
+				while (i >= 0)
+				{
+					if (__this__[i] == x)
+						return i;
+					i--;
+				}
+				return -1;
+			}
 			Array.prototype["iterator"] = function() {
 				return {
 					cur : 0,

+ 31 - 0
std/java/_std/Array.hx

@@ -362,6 +362,37 @@ import java.NativeArray;
 		return false;
 	}
 
+	public function indexOf(x : T, ?fromIndex:Int) : Int {
+		var len = length, a = __a, i:Int = (fromIndex == null) ? 0 : fromIndex;
+		if (i < 0)
+		{
+			i += len;
+			if (i < 0) i = 0;
+		}
+		while (i < len)
+		{
+			if (a[i] == x)
+				return i;
+			i++;
+		}
+		return -1;
+	}
+
+	public function lastIndexOf(x : T, ?fromIndex:Int) : Int {
+		var len = length, a = __a, i:Int = (fromIndex == null) ? len - 1 : fromIndex;
+		if (i >= len)
+			i = len - 1;
+		else if (i < 0)
+			i += len;
+		while (i >= 0)
+		{
+			if (a[i] == x)
+				return i;
+			i--;
+		}
+		return -1;
+	}
+
 	public function copy() : Array<T>
 	{
 		var len = length;

+ 9 - 1
std/js/_std/Array.hx

@@ -42,7 +42,15 @@ extern class Array<T> {
 	}
 
 	inline function remove( x : T ) : Bool {
-		return untyped HxOverrides.remove(this,x);
+		return @:privateAccess HxOverrides.remove(this,x);
+	}
+
+	inline function indexOf( x : T, ?fromIndex:Int ) : Int {
+		return @:privateAccess HxOverrides.indexOf(this,x,(fromIndex!=null)?fromIndex:0);
+	}
+
+	inline function lastIndexOf( x : T, ?fromIndex:Int ) : Int {
+		return @:privateAccess HxOverrides.lastIndexOf(this,x,(fromIndex!=null)?fromIndex:length-1);
 	}
 
 	inline function copy() : Array<T> {

+ 35 - 17
std/js/_std/HxOverrides.hx

@@ -83,17 +83,41 @@ class HxOverrides {
 		return (untyped s).substr(pos, len);
 	}
 
-	static function remove<T>( a : Array<T>, obj : T ) {
-		var i = 0;
-		var l = a.length;
-		while( i < l ) {
-			if( a[i] == obj ) {
-				a.splice(i,1);
-				return true;
-			}
+	static function indexOf<T>( a : Array<T>, obj : T, i : Int) {
+		var len = a.length;
+		if (i < 0) {
+			i += len;
+			if (i < 0) i = 0;
+		}
+		while (i < len)
+		{
+			if (untyped __js__("a[i] === obj"))
+				return i;
 			i++;
 		}
-		return false;
+		return -1;
+	}
+
+	static function lastIndexOf<T>( a : Array<T>, obj : T, i : Int) {
+		var len = a.length;
+		if (i >= len)
+			i = len - 1;
+		else if (i < 0)
+			i += len;
+		while (i >= 0)
+		{
+			if (untyped __js__("a[i] === obj"))
+				return i;
+			i--;
+		}
+		return -1;
+	}
+
+	static function remove<T>( a : Array<T>, obj : T ) {
+		var i = indexOf(a, obj, 0);
+		if( i == -1 ) return false;
+		a.splice(i,1);
+		return true;
 	}
 
 	static function iter<T>( a : Array<T> ) : Iterator<T> untyped {
@@ -110,14 +134,8 @@ class HxOverrides {
 	}
 
 	static function __init__() untyped {
-		__feature__('HxOverrides.remove',
-			if( Array.prototype.indexOf ) __js__('HxOverrides').remove = function(a,o) {
-				var i = a.indexOf(o);
-				if( i == -1 ) return false;
-				a.splice(i,1);
-				return true;
-			}
-		);
+		__feature__('HxOverrides.indexOf', if( Array.prototype.indexOf ) __js__("HxOverrides").indexOf = function(a,o,i) return Array.prototype.indexOf.call(a, o, i));
+		__feature__('HxOverrides.lastIndexOf', if( Array.prototype.lastIndexOf ) __js__("HxOverrides").lastIndexOf = function(a,o,i) return Array.prototype.lastIndexOf.call(a, o, i));
 		#if mt
 		if( String.prototype.cca == null ) String.prototype.cca = String.prototype.charCodeAt;
 		#end

+ 34 - 0
std/neko/_std/Array.hx

@@ -145,6 +145,40 @@
 		return false;
 	}
 
+	public function indexOf(x : T, ?fromIndex:Int) : Int {
+		var len = length;
+		var i:Int = (fromIndex != null) ? fromIndex : 0;
+		var a = __a;
+		if (i < 0) {
+			i += len;
+			if (i < 0) i = 0;
+		}
+		while (i < len)
+		{
+			if (a[i] == x)
+				return i;
+			i++;
+		}
+		return -1;
+	}
+
+	public function lastIndexOf(x : T, ?fromIndex:Int) : Int {
+		var len = length;
+		var i:Int = (fromIndex != null) ? fromIndex : len - 1;
+		var a = __a;
+		if (i >= len)
+			i = len - 1;
+		else if (i < 0)
+			i += len;
+		while (i >= 0)
+		{
+			if (a[i] == x)
+				return i;
+			i--;
+		}
+		return -1;
+	}
+
 	public function reverse() : Void {
 		var i = 0;
 		var l = this.length;

+ 32 - 0
std/php/Boot.hx

@@ -105,6 +105,38 @@ class _hx_array implements ArrayAccess, IteratorAggregate {
 		return false;
 	}
 
+	function indexOf($x, $fromIndex) {
+		$i = ($fromIndex === null) ? 0 : $fromIndex;
+		$len = $this->length;
+		$a = $this->a;
+		if ($i < 0) {
+			$i += $len;
+			if ($i < 0) $i = 0;
+		}
+		while ($i < $len) {
+			if ($a[$i] === $x)
+				return $i;
+			$i++;
+		}
+		return -1;
+	}
+
+	function lastIndexOf($x, $fromIndex) {
+		$len = $this->length;
+		$i = ($fromIndex === null) ? $len - 1 : $fromIndex;
+		$a = $this->a;
+		if ($i >= $len)
+			$i = $len - 1;
+		else if ($i < 0)
+			$i += $len;
+		while ($i >= 0) {
+			if ($a[$i] === $x)
+				return $i;
+			$i--;
+		}
+		return -1;
+	}
+
 	function removeAt($pos) {
 		if(array_key_exists($pos, $this->a)) {
 			unset($this->a[$pos]);

+ 35 - 0
tests/unit/unitstd/Array.unit.hx

@@ -198,6 +198,41 @@ a == [i0, i1];
 a.remove(null) == false;
 a == [i0, i1];
 
+// indexOf
+[].indexOf(10) == -1;
+[10].indexOf(10) == 0;
+[10, 10].indexOf(10) == 0;
+[2, 10].indexOf(10) == 1;
+[2, 5].indexOf(10) == -1;
+["foo", "bar", "bar", "baz"].indexOf("bar") == 1;
+[1, 10, 10, 1].indexOf(10, 0) == 1;
+[1, 10, 10, 1].indexOf(10, 1) == 1;
+[1, 10, 10, 1].indexOf(10, 2) == 2;
+[1, 10, 10, 1].indexOf(10, 3) == -1;
+[1, 10, 10, 1].indexOf(10, 4) == -1;
+[1, 10, 10, 1].indexOf(10, -1) == -1;
+[1, 10, 10, 1].indexOf(10, -2) == 2;
+[1, 10, 10, 1].indexOf(10, -3) == 1;
+[1, 10, 10, 1].indexOf(10, -5) == 1;
+
+// lastIndexOf
+[].lastIndexOf(10) == -1;
+[10].lastIndexOf(10) == 0;
+[10, 10].lastIndexOf(10) == 1;
+[2, 10].lastIndexOf(10) == 1;
+[2, 5].lastIndexOf(10) == -1;
+["foo", "bar", "bar", "baz"].lastIndexOf("bar") == 2;
+[1, 10, 10, 1].lastIndexOf(10, 4) == 2;
+[1, 10, 10, 1].lastIndexOf(10, 3) == 2;
+[1, 10, 10, 1].lastIndexOf(10, 2) == 2;
+[1, 10, 10, 1].lastIndexOf(10, 1) == 1;
+[1, 10, 10, 1].lastIndexOf(10, 0) == -1;
+[1, 10, 10, 1].lastIndexOf(10, -1) == 2;
+[1, 10, 10, 1].lastIndexOf(10, -2) == 2;
+[1, 10, 10, 1].lastIndexOf(10, -3) == 1;
+[1, 10, 10, 1].lastIndexOf(10, -4) == -1;
+[1, 10, 10, 1].lastIndexOf(10, -5) == -1;
+
 // copy
 var i0 = new IntWrap(1);
 var i1 = new IntWrap(1);