Merge pull request #50349 from Calinou/array-add-some-every
Add `any()` and `all()` methods to Array
This commit is contained in:
commit
3f8d86b076
4 changed files with 93 additions and 0 deletions
|
@ -501,6 +501,50 @@ Variant Array::reduce(const Callable &p_callable, const Variant &p_accum) const
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Array::any(const Callable &p_callable) const {
|
||||||
|
const Variant *argptrs[1];
|
||||||
|
for (int i = 0; i < size(); i++) {
|
||||||
|
argptrs[0] = &get(i);
|
||||||
|
|
||||||
|
Variant result;
|
||||||
|
Callable::CallError ce;
|
||||||
|
p_callable.call(argptrs, 1, result, ce);
|
||||||
|
if (ce.error != Callable::CallError::CALL_OK) {
|
||||||
|
ERR_FAIL_V_MSG(false, "Error calling method from 'any': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.operator bool()) {
|
||||||
|
// Return as early as possible when one of the conditions is `true`.
|
||||||
|
// This improves performance compared to relying on `filter(...).size() >= 1`.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Array::all(const Callable &p_callable) const {
|
||||||
|
const Variant *argptrs[1];
|
||||||
|
for (int i = 0; i < size(); i++) {
|
||||||
|
argptrs[0] = &get(i);
|
||||||
|
|
||||||
|
Variant result;
|
||||||
|
Callable::CallError ce;
|
||||||
|
p_callable.call(argptrs, 1, result, ce);
|
||||||
|
if (ce.error != Callable::CallError::CALL_OK) {
|
||||||
|
ERR_FAIL_V_MSG(false, "Error calling method from 'all': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(result.operator bool())) {
|
||||||
|
// Return as early as possible when one of the inverted conditions is `false`.
|
||||||
|
// This improves performance compared to relying on `filter(...).size() >= array_size().`.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
struct _ArrayVariantSort {
|
struct _ArrayVariantSort {
|
||||||
_FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const {
|
_FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const {
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
|
|
|
@ -108,6 +108,8 @@ public:
|
||||||
Array filter(const Callable &p_callable) const;
|
Array filter(const Callable &p_callable) const;
|
||||||
Array map(const Callable &p_callable) const;
|
Array map(const Callable &p_callable) const;
|
||||||
Variant reduce(const Callable &p_callable, const Variant &p_accum) const;
|
Variant reduce(const Callable &p_callable, const Variant &p_accum) const;
|
||||||
|
bool any(const Callable &p_callable) const;
|
||||||
|
bool all(const Callable &p_callable) const;
|
||||||
|
|
||||||
bool operator<(const Array &p_array) const;
|
bool operator<(const Array &p_array) const;
|
||||||
bool operator<=(const Array &p_array) const;
|
bool operator<=(const Array &p_array) const;
|
||||||
|
|
|
@ -1859,6 +1859,8 @@ static void _register_variant_builtin_methods() {
|
||||||
bind_method(Array, filter, sarray("method"), varray());
|
bind_method(Array, filter, sarray("method"), varray());
|
||||||
bind_method(Array, map, sarray("method"), varray());
|
bind_method(Array, map, sarray("method"), varray());
|
||||||
bind_method(Array, reduce, sarray("method", "accum"), varray(Variant()));
|
bind_method(Array, reduce, sarray("method", "accum"), varray(Variant()));
|
||||||
|
bind_method(Array, any, sarray("method"), varray());
|
||||||
|
bind_method(Array, all, sarray("method"), varray());
|
||||||
bind_method(Array, max, sarray(), varray());
|
bind_method(Array, max, sarray(), varray());
|
||||||
bind_method(Array, min, sarray(), varray());
|
bind_method(Array, min, sarray(), varray());
|
||||||
|
|
||||||
|
|
|
@ -123,6 +123,48 @@
|
||||||
</constructor>
|
</constructor>
|
||||||
</constructors>
|
</constructors>
|
||||||
<methods>
|
<methods>
|
||||||
|
<method name="all" qualifiers="const">
|
||||||
|
<return type="bool" />
|
||||||
|
<argument index="0" name="method" type="Callable" />
|
||||||
|
<description>
|
||||||
|
Calls the provided [Callable] on each element in the array and returns [code]true[/code] if the [Callable] returns [code]true[/code] for [i]all[/i] elements in the array. If the [Callable] returns [code]false[/code] for one array element or more, this method returns [code]false[/code].
|
||||||
|
The callable's method should take one [Variant] parameter (the current array element) and return a boolean value.
|
||||||
|
[codeblock]
|
||||||
|
func _ready():
|
||||||
|
print([6, 10, 6].all(greater_than_5)) # Prints True (3 elements evaluate to `true`).
|
||||||
|
print([4, 10, 4].all(greater_than_5)) # Prints False (1 elements evaluate to `true`).
|
||||||
|
print([4, 4, 4].all(greater_than_5)) # Prints False (0 elements evaluate to `true`).
|
||||||
|
|
||||||
|
print([6, 10, 6].all(func(number): return number > 5)) # Prints True. Same as the first line above, but using lambda function.
|
||||||
|
|
||||||
|
func greater_than_5(number):
|
||||||
|
return number > 5
|
||||||
|
[/codeblock]
|
||||||
|
See also [method any], [method filter], [method map] and [method reduce].
|
||||||
|
[b]Note:[/b] Unlike relying on the size of an array returned by [method filter], this method will return as early as possible to improve performance (especially with large arrays).
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
|
<method name="any" qualifiers="const">
|
||||||
|
<return type="bool" />
|
||||||
|
<argument index="0" name="method" type="Callable" />
|
||||||
|
<description>
|
||||||
|
Calls the provided [Callable] on each element in the array and returns [code]true[/code] if the [Callable] returns [code]true[/code] for [i]one or more[/i] elements in the array. If the [Callable] returns [code]false[/code] for all elements in the array, this method returns [code]false[/code].
|
||||||
|
The callable's method should take one [Variant] parameter (the current array element) and return a boolean value.
|
||||||
|
[codeblock]
|
||||||
|
func _ready():
|
||||||
|
print([6, 10, 6].any(greater_than_5)) # Prints True (3 elements evaluate to `true`).
|
||||||
|
print([4, 10, 4].any(greater_than_5)) # Prints True (1 elements evaluate to `true`).
|
||||||
|
print([4, 4, 4].any(greater_than_5)) # Prints False (0 elements evaluate to `true`).
|
||||||
|
|
||||||
|
print([6, 10, 6].any(func(number): return number > 5)) # Prints True. Same as the first line above, but using lambda function.
|
||||||
|
|
||||||
|
func greater_than_5(number):
|
||||||
|
return number > 5
|
||||||
|
[/codeblock]
|
||||||
|
See also [method all], [method filter], [method map] and [method reduce].
|
||||||
|
[b]Note:[/b] Unlike relying on the size of an array returned by [method filter], this method will return as early as possible to improve performance (especially with large arrays).
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="append">
|
<method name="append">
|
||||||
<return type="void" />
|
<return type="void" />
|
||||||
<argument index="0" name="value" type="Variant" />
|
<argument index="0" name="value" type="Variant" />
|
||||||
|
@ -232,6 +274,7 @@
|
||||||
func remove_1(number):
|
func remove_1(number):
|
||||||
return number != 1
|
return number != 1
|
||||||
[/codeblock]
|
[/codeblock]
|
||||||
|
See also [method any], [method all], [method map] and [method reduce].
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="find" qualifiers="const">
|
<method name="find" qualifiers="const">
|
||||||
|
@ -333,6 +376,7 @@
|
||||||
func negate(number):
|
func negate(number):
|
||||||
return -number
|
return -number
|
||||||
[/codeblock]
|
[/codeblock]
|
||||||
|
See also [method filter], [method reduce], [method any] and [method all].
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="max" qualifiers="const">
|
<method name="max" qualifiers="const">
|
||||||
|
@ -398,6 +442,7 @@
|
||||||
func sum(accum, number):
|
func sum(accum, number):
|
||||||
return accum + number
|
return accum + number
|
||||||
[/codeblock]
|
[/codeblock]
|
||||||
|
See also [method map], [method filter], [method any] and [method all].
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="remove_at">
|
<method name="remove_at">
|
||||||
|
|
Loading…
Reference in a new issue