mirror of https://github.com/Icinga/icinga2.git
Add map/reduce and filter functionality for the Array class
fixes #12247
This commit is contained in:
parent
0d02b01c02
commit
a3815e4efd
|
@ -692,6 +692,43 @@ Signature:
|
||||||
|
|
||||||
Returns a new array with all elements of the current array in reverse order.
|
Returns a new array with all elements of the current array in reverse order.
|
||||||
|
|
||||||
|
### <a id="array-map"></a> Array#map
|
||||||
|
|
||||||
|
Signature:
|
||||||
|
|
||||||
|
function map(func);
|
||||||
|
|
||||||
|
Calls `func(element)` for each of the elements in the array and returns
|
||||||
|
a new array containing the return values of these function calls.
|
||||||
|
|
||||||
|
### <a id="array-reduce"></a> Array#reduce
|
||||||
|
|
||||||
|
Signature:
|
||||||
|
|
||||||
|
function reduce(func);
|
||||||
|
|
||||||
|
Reduces the elements of the array into a single value by calling the provided
|
||||||
|
function `func` as `func(a, b)` repeatedly where `a` is the previous result of
|
||||||
|
function call (null initially) and `b` is an element of the array.
|
||||||
|
|
||||||
|
### <a id="array-filter"> Array#filter
|
||||||
|
|
||||||
|
Signature:
|
||||||
|
|
||||||
|
function filter(func);
|
||||||
|
|
||||||
|
Returns a copy of the array containing only the elements for which `func(element)`
|
||||||
|
is true.
|
||||||
|
|
||||||
|
### <a id="array-filter"> Array#unique
|
||||||
|
|
||||||
|
Signature:
|
||||||
|
|
||||||
|
function unique();
|
||||||
|
|
||||||
|
Returns a copy of the array with all duplicate elements removed. The original order
|
||||||
|
of the array is not preserved.
|
||||||
|
|
||||||
## <a id="dictionary-type"></a> Dictionary type
|
## <a id="dictionary-type"></a> Dictionary type
|
||||||
|
|
||||||
Inherits methods from the [Object type](19-library-reference.md#object-type).
|
Inherits methods from the [Object type](19-library-reference.md#object-type).
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "base/functionwrapper.hpp"
|
#include "base/functionwrapper.hpp"
|
||||||
#include "base/scriptframe.hpp"
|
#include "base/scriptframe.hpp"
|
||||||
#include "base/objectlock.hpp"
|
#include "base/objectlock.hpp"
|
||||||
|
#include "base/exception.hpp"
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
|
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
@ -94,6 +95,11 @@ static Array::Ptr ArraySort(const std::vector<Value>& args)
|
||||||
ObjectLock olock(arr);
|
ObjectLock olock(arr);
|
||||||
std::sort(arr->Begin(), arr->End());
|
std::sort(arr->Begin(), arr->End());
|
||||||
} else {
|
} else {
|
||||||
|
Function::Ptr function = args[0];
|
||||||
|
|
||||||
|
if (vframe->Sandboxed && !function->IsSideEffectFree())
|
||||||
|
BOOST_THROW_EXCEPTION(ScriptError("Sort function must be side-effect free."));
|
||||||
|
|
||||||
ObjectLock olock(arr);
|
ObjectLock olock(arr);
|
||||||
std::sort(arr->Begin(), arr->End(), boost::bind(ArraySortCmp, args[0], _1, _2));
|
std::sort(arr->Begin(), arr->End(), boost::bind(ArraySortCmp, args[0], _1, _2));
|
||||||
}
|
}
|
||||||
|
@ -137,6 +143,86 @@ static Array::Ptr ArrayReverse(void)
|
||||||
return self->Reverse();
|
return self->Reverse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Array::Ptr ArrayMap(const Function::Ptr& function)
|
||||||
|
{
|
||||||
|
ScriptFrame *vframe = ScriptFrame::GetCurrentFrame();
|
||||||
|
Array::Ptr self = static_cast<Array::Ptr>(vframe->Self);
|
||||||
|
|
||||||
|
if (vframe->Sandboxed && !function->IsSideEffectFree())
|
||||||
|
BOOST_THROW_EXCEPTION(ScriptError("Map function must be side-effect free."));
|
||||||
|
|
||||||
|
Array::Ptr result = new Array();
|
||||||
|
|
||||||
|
ObjectLock olock(self);
|
||||||
|
BOOST_FOREACH(const Value& item, self) {
|
||||||
|
ScriptFrame uframe;
|
||||||
|
std::vector<Value> args;
|
||||||
|
args.push_back(item);
|
||||||
|
result->Add(function->Invoke(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Value ArrayReduce(const Function::Ptr& function)
|
||||||
|
{
|
||||||
|
ScriptFrame *vframe = ScriptFrame::GetCurrentFrame();
|
||||||
|
Array::Ptr self = static_cast<Array::Ptr>(vframe->Self);
|
||||||
|
|
||||||
|
if (vframe->Sandboxed && !function->IsSideEffectFree())
|
||||||
|
BOOST_THROW_EXCEPTION(ScriptError("Reduce function must be side-effect free."));
|
||||||
|
|
||||||
|
Value result;
|
||||||
|
|
||||||
|
ObjectLock olock(self);
|
||||||
|
BOOST_FOREACH(const Value& item, self) {
|
||||||
|
ScriptFrame uframe;
|
||||||
|
std::vector<Value> args;
|
||||||
|
args.push_back(result);
|
||||||
|
args.push_back(item);
|
||||||
|
result = function->Invoke(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Array::Ptr ArrayFilter(const Function::Ptr& function)
|
||||||
|
{
|
||||||
|
ScriptFrame *vframe = ScriptFrame::GetCurrentFrame();
|
||||||
|
Array::Ptr self = static_cast<Array::Ptr>(vframe->Self);
|
||||||
|
|
||||||
|
if (vframe->Sandboxed && !function->IsSideEffectFree())
|
||||||
|
BOOST_THROW_EXCEPTION(ScriptError("Filter function must be side-effect free."));
|
||||||
|
|
||||||
|
Array::Ptr result = new Array();
|
||||||
|
|
||||||
|
ObjectLock olock(self);
|
||||||
|
BOOST_FOREACH(const Value& item, self) {
|
||||||
|
ScriptFrame uframe;
|
||||||
|
std::vector<Value> args;
|
||||||
|
args.push_back(item);
|
||||||
|
if (function->Invoke(args))
|
||||||
|
result->Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Array::Ptr ArrayUnique(void)
|
||||||
|
{
|
||||||
|
ScriptFrame *vframe = ScriptFrame::GetCurrentFrame();
|
||||||
|
Array::Ptr self = static_cast<Array::Ptr>(vframe->Self);
|
||||||
|
|
||||||
|
std::set<Value> result;
|
||||||
|
|
||||||
|
ObjectLock olock(self);
|
||||||
|
BOOST_FOREACH(const Value& item, self) {
|
||||||
|
result.insert(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Array::FromSet(result);
|
||||||
|
}
|
||||||
|
|
||||||
Object::Ptr Array::GetPrototype(void)
|
Object::Ptr Array::GetPrototype(void)
|
||||||
{
|
{
|
||||||
static Dictionary::Ptr prototype;
|
static Dictionary::Ptr prototype;
|
||||||
|
@ -154,6 +240,10 @@ Object::Ptr Array::GetPrototype(void)
|
||||||
prototype->Set("shallow_clone", new Function(WrapFunction(ArrayShallowClone), true));
|
prototype->Set("shallow_clone", new Function(WrapFunction(ArrayShallowClone), true));
|
||||||
prototype->Set("join", new Function(WrapFunction(ArrayJoin), true));
|
prototype->Set("join", new Function(WrapFunction(ArrayJoin), true));
|
||||||
prototype->Set("reverse", new Function(WrapFunction(ArrayReverse), true));
|
prototype->Set("reverse", new Function(WrapFunction(ArrayReverse), true));
|
||||||
|
prototype->Set("map", new Function(WrapFunction(ArrayMap), true));
|
||||||
|
prototype->Set("reduce", new Function(WrapFunction(ArrayReduce), true));
|
||||||
|
prototype->Set("filter", new Function(WrapFunction(ArrayFilter), true));
|
||||||
|
prototype->Set("unique", new Function(WrapFunction(ArrayUnique), true));
|
||||||
}
|
}
|
||||||
|
|
||||||
return prototype;
|
return prototype;
|
||||||
|
|
|
@ -118,6 +118,15 @@ public:
|
||||||
return std::set<T>(Begin(), End());
|
return std::set<T>(Begin(), End());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static Array::Ptr FromSet(const std::set<T>& v)
|
||||||
|
{
|
||||||
|
Array::Ptr result = new Array();
|
||||||
|
ObjectLock olock(result);
|
||||||
|
std::copy(v.begin(), v.end(), std::back_inserter(result->m_Data));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
virtual Object::Ptr Clone(void) const override;
|
virtual Object::Ptr Clone(void) const override;
|
||||||
|
|
||||||
Array::Ptr Reverse(void) const;
|
Array::Ptr Reverse(void) const;
|
||||||
|
|
Loading…
Reference in New Issue