The description in the documentation is really simple and maybe it is because these methods were not made with 2d arrays in mind but since the docs say that if the elements cant be compare the result will be null, but these do compare in same way I thought maybe there's a logic to these results that is not explained in the docs.

Basically I was experimenting with min and max in 2d arrays holding strings and came up with this:

var arr :Array = [["Taaaa",6,"yaa"],["T",10,"yaa"],["Teeee",7,"yaa"]]
print(arr.max()) #result ["Teeee",7,"yaa"]
print(arr.min()) #result ["Teeee",7,"yaa"]

both of these have the same value and I was wonder how could that be, while playing with the methods I realised it cares about length of the strings and the alphabetical order and it seems to be case sensitive

var arr :Array = [["Taaaa",6,"yaa"],["T",10,"yaa"],["Zeeee",7,"yaa"]]
print(arr.max())  #result  ["Zeeee",7,"yaa"]
print(arr.min())  #result  ["Zeeee",7,"yaa"]

var arr :Array = [["taaaa",6,"yaa"],["T",10,"yaa"],["Zeeee",7,"yaa"]]
print(arr.max())  #result  ["taaaa",6,"yaa"]
print(arr.min())  #result  ["Zeeee",7,"yaa"]

Welcome to the forums @llHate!

My guess is that the min and max functions try to convert the first element of the array into a integer (or float), and then use that for comparison. Since strings can be converted to a series of ASCII or Unicode characters, it may be that Godot's min and max functions calculate using these encodings. That would explain the result in the 3rd snippet, as lowercase letters are higher/larger in ASCII (not sure on Unicode) than uppercase letters, leading to taaaa being a higher number than Zeeee simply because the Z is uppercase. (In ASCII, t is 116 in decimal while Z is 90)

@TwistedTwigleg Thanks for the welcoming and the reply.

While It may have to do with characters been turn into ASCII it seems to be something more going on I thought maybe I could use it to my advantage but I cant manage to get the expected result all the time.

Some more testing with 2d arrays:

[["aza"],["aba"],["aaa"]] max: ["aza"] min: ["aza"] [["a6a"],["aaa"],["aa"]] max: ["aaa"] min: ["aaa"]

It gets more confusing with uppercase letters. [["aa"],["aaa"],["A"]] max: ["aaa"] min: ["aaa"] [["aa"],["aaa"],["AAA"]] max: ["aaa"] min: ["aaa"] [["aaa"],["Aaa"],["AAA"]] max: ["aaa"] min: ["aaa"] [["aaa"],["Aaz"],["AAA"]] max: ["aaa"] min: ["aaa"] [["aaa"],["aaz"],["AAA"]] max: ["aaz"] min: ["aaz"]

I seems to compare only the very first character and if it has the same value it goes to the next one:

[["aba"],["aaz"],["AcA"],["baA"]] max: ["baA"] min: ["baA"] [["abc"],["zxy"],["ABC"],["ZXY"]] max: ["zxy"] min: ["zxy"]

With 1d arrays everything works as expected lowercase characters with higher values got picked by max() and uppercase which have lower values than their homonymous in lowercases got picked by min(). ["abc","zxy","ABC","ZXY"] max: zxy min: ABC [["abc"],["zxy"],["ABC"],["ZXY"]] max:[zxy] min: [zxy]

Integers act the same way as strings in 2d arrays. [[0],[7],[8]] max: [8] min: [8] [0,7,8] max: 8 min: 0

But negative values result in different results and this may be because of the ASCII or UNICODE conversion taking in consideration the "-" simbol but when there's no string inside the 2d array it didn't care about the negative value unlike the 1d array. [["a",0],["a",7],["a",8],["a",-0]] max: ["a",8] min: ["a",0] [[0],[7],[8],[-0]] max: [8] min: [8] [[1],[7],[8],[-10]] max: [8] min: [8] [1,7,8,-0] max: 8 min: 0

TLDR: I think min() is malfunctioning in 2d arrays.

The best way would be to check the source code but I never used github before and the only language I know is Gdscript so I don't think I could understand the C++ source code. Also I can work around it easily.

I checked the source code but I couldn't figure out the problem

Here is the implementation of Array.min(): https://github.com/godotengine/godot/blob/3.2/core/array.cpp#L408

Variant Array::min() const {

	Variant minval;
	for (int i = 0; i < size(); i++) {
		if (i == 0) {
			minval = get(i);
		} else {
			bool valid;
			Variant ret;
			Variant test = get(i);
			Variant::evaluate(Variant::OP_LESS, test, minval, ret, valid);
			if (!valid) {
				return Variant(); //not a valid comparison
			}
			if (bool(ret)) {
				//is less
				minval = test;
			}
		}
	}
	return minval;
}

And here is Variant:evaluate, where it compares two arrays: https://github.com/godotengine/godot/blob/3.2/core/variant_op.cpp#L596

			CASE_TYPE(math, OP_LESS, ARRAY) {
				if (p_b.type != ARRAY)
					_RETURN_FAIL;

				const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem);
				const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem);

				int l = arr_a->size();
				if (arr_b->size() < l)
					_RETURN(false);
				for (int i = 0; i < l; i++) {
					if (!((*arr_a)[i] < (*arr_b)[i])) {
						_RETURN(true);
					}
				}

				_RETURN(false);
			}
2 years later