Array.sort() issue in Haxe when trying to find median from a set of numbers

In AS3 I had a function to find the Median value, however when trying to translate it in Haxe, it throws errors, it seems to be related to the Array sort() function but I am not exactly sure how to fix this,

// test case, should return 3
var myarr2:Array<Float> = new Array();
myarr2 = [3, 5, 4, 4, 1, 1, 2, 3];
trace( tMath.Median(myarr2) );

// functions
public inline function IsEven(value:Float):Bool {
	return (value % 2) > 0.5? false : true;
};

public inline function Median(numbers:Array<Float>):Float {

	var median:Float  = 0;
	var numsLen:Float = numbers.length;
	
	numbers.sort();
	
	if (this.IsEven(numsLen)) { // is even
		// average of two middle numbers
		median = (numbers[numsLen / 2 - 1] + numbers[numsLen / 2]) / 2;
	} else { // is odd
		// middle number only
		median = numbers[(numsLen - 1) / 2];
	}
	return median;
	
};

In Haxe, the comparison function is not optional. To put the numbers in ascending order, you have to do this:

numbers.sort(function(a:Float, b:Float):Int {
    return b == a ? 0 : (b > a ? -1 : 1);
});

To make this easier in the future, you might want to save a copy of this class. Then when you need to sort, you can just pick one of those functions.

2 Likes

Ahh I see, I expected these to come as standard and be optional like in AS3, thank you, those will come in handy.

I was getting errors after that though, that the array indexes should be Int instead of Floats, so I used Std.int() and seems the function works though. Was that a safe thing to do?

Full function:

public inline function Median(numbers:Array<Float>):Float {

	var median:Float  = 0.0;
	var numsLen:Float = numbers.length;
	
	numbers.sort(function(a:Float, b:Float):Int { return b == a ? 0 : (b > a ? -1 : 1); });
	
	if (this.IsEven(numsLen)) { // is even
		// average of two middle numbers
		median = (numbers[Std.int(numsLen / 2 - 1)] + numbers[Std.int(numsLen / 2)]) / 2;
	} else { // is odd
		// middle number only
		median = numbers[Std.int((numsLen - 1) / 2)];
	}
	return median;
	
};

Yes, you need to convert to an integer, and yes, Std.int() is one correct way to do that. In another situation, you might use Math.round(), Math.floor(), or Math.ceil() instead. (These functions also convert floats to ints, but they use different rounding rules.)