From ad693e67ecfcdb1d887b5aa30fec15ec5e0c02f5 Mon Sep 17 00:00:00 2001 From: Sfinktah Bungholio Date: Wed, 1 Nov 2017 05:51:11 +1100 Subject: [PATCH] added test.cpp --- lodash.hpp | 70 +++++++++++++----------------- test.cpp | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 151 insertions(+), 41 deletions(-) create mode 100644 test.cpp diff --git a/lodash.hpp b/lodash.hpp index d105f3e..d74a8af 100644 --- a/lodash.hpp +++ b/lodash.hpp @@ -361,28 +361,21 @@ namespace _ auto k = i->first; helper::add_to_container(result, k); } - //for (auto i = container.begin(); i != container.end(); ++i) - //{ - // helper::add_to_container(result, i->key()); - //} return result; } // sfink - keys2 - template - ResultContainer keys2(Container container) + template + auto keys2(const Container& container) { - ResultContainer result; - for (auto i = container.begin(); i != container.end(); ++i) - { - auto k = i->first; - helper::add_to_container(result, k); - } + return keys>(container); + //typename Container::key_type result; //for (auto i = container.begin(); i != container.end(); ++i) //{ - // helper::add_to_container(result, i->key()); + // auto k = i->first; + // helper::add_to_container(result, k); //} - return result; + //return result; } // MDN - The slice() method returns a shallow copy of a portion of an array into a @@ -450,7 +443,7 @@ namespace _ /// TODO Implement initialValue as optional: "[Optional] Value to use as the first argument to the first call of the callback. If no initial value is supplied, the first element in the array will be used. Calling reduce on an empty array without an initial value is an error." /// TODO Implement full range of functionality as described in https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce?v=b template - Memo reduce(const Container container, Function function, Memo initialValue) + Memo reduce(const Container& container, Function function, Memo initialValue) { for (auto i = container.begin(); i != container.end(); ++i) { @@ -459,20 +452,20 @@ namespace _ return initialValue; } - /// Applies a function against an accumulator and each element in the array-container (from left to right) to reduce it to a single value. + /// `reduce` for sequence containers with 4 argument callback /// The container. - /// The callback, callback(, currentValue) + /// callback(, currentValue, currentIndex, ) /// Value to use as the first argument to the first call of the callback. /// The value that results from the reduction. /// - /// std::vector v{ 1, 2, 3 }; - /// cout << v.reduce([](accumulator, currentValue, currentIndex, container) { - /// return accumulator + "Index: "s + std::to_string(currentIndex) + " = "s + std::to_string(currentValue) + '\n'; - /// }, std::string{}); - /// + /// std::vector v{ 1, 2, 3 }; + /// count << _::reduceArray(v, [](auto accumulator, auto currentValue, auto currentIndex, auto container) { + /// return accumulator + "Index: "s + std::to_string(currentIndex) + " = "s + std::to_string(currentValue) + '\n'; + /// }, std::string{}) + /// /// TODO Implement initialValue as optional: "[Optional] Value to use as the first argument to the first call of the callback. If no initial value is supplied, the first element in the array will be used. Calling reduce on an empty array without an initial value is an error." template - Memo reduce2(const Container container, Function function, Memo initialValue) + Memo reduceArray(const Container& container, Function function, Memo initialValue) { each_with_distance(container, [&](const typename Container::value_type& value, const size_t index) { initialValue = function(initialValue, value, index, container); @@ -481,48 +474,43 @@ namespace _ } - /// Applies a function against an accumulator and each element in the container (from left to right) to reduce it to a single value. + /// `reduce` for associative containers with 4 argument callback + /// + /// /// The container. - /// The callback, callback(, currentValue) + /// callback(, currentValue, currentKey, ) /// Value to use as the first argument to the first call of the callback. /// The value that results from the reduction. - /// - /// std::vector v{ 1, 2, 3 }; - /// cout << v.reduce([](accumulator, currentValue, currentIndex, container) { - /// return accumulator + "Index: "s + std::to_string(currentIndex) + " = "s + std::to_string(currentValue) + '\n'; - /// }, std::string{}); - /// /// TODO Implement initialValue as optional: "[Optional] Value to use as the first argument to the first call of the callback. If no initial value is supplied, the first element in the array will be used. Calling reduce on an empty array without an initial value is an error." template - Memo reduceMap(const Container container, Function function, Memo initialValue) + Memo reduceObject(const Container& container, Function function, Memo initialValue) { // ResultContainer result; - auto keys = _::keys(container); + auto keys = _::keys2(container); for (const auto& key : keys) { - initialValue = function(initialValue, container[key], key, container); + // const auto& value = container.at(key); + auto value = container.at(key); + initialValue = function(initialValue, value, key, container); } return initialValue; } - //for (auto i = container.begin(); i != container.end(); ++i) { - // function(*i, std::distance(container.begin(), i)); - //} template - Memo inject(const Container container, Function function, Memo initialValue) + Memo inject(const Container& container, Function function, Memo initialValue) { return reduce(container, function, initialValue); } template - Memo foldl(const Container container, Function function, Memo initialValue) + Memo foldl(const Container& container, Function function, Memo initialValue) { return reduce(container, function, initialValue); } // reduce_right/foldr template - Memo reduce_right(const Container container, Function function, Memo initialValue) + Memo reduce_right(const Container& container, Function function, Memo initialValue) { for (typename Container::const_reverse_iterator i = container.rbegin(); i != container.rend(); ++i) @@ -533,7 +521,7 @@ namespace _ } template - Memo foldr(const Container container, Function function, Memo initialValue) + Memo foldr(const Container& container, Function function, Memo initialValue) { return reduce_right(container, function, initialValue); } diff --git a/test.cpp b/test.cpp new file mode 100644 index 0000000..337139d --- /dev/null +++ b/test.cpp @@ -0,0 +1,122 @@ +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +#include +// #include +#include +// #include +// #include +#include +// #include +// #include +// #include +// #include +#include +// #include +// #include +// #include +// #include +#include +// #include +// #include +// #include +// #include +#include + +#include "lodash.hpp" +// #include "test/json.hpp" + +using namespace std::string_literals; + +#define TEST(NAME, ...) \ + std::cout << "\n\n********\n" << #NAME << ":\n" << (__VA_ARGS__)(); + +template +std::string join(const T& elements, const char* const separator) { + std::ostringstream os; + + const char* _separator = ""; + for (auto& item : elements) { + os << _separator << item; + _separator = separator; + } + return os.str(); +} + +int main(int argc, const char** argv) { + + // instead, you could also write (which looks very similar to the JSON above) + // json object = { + // {"pi", 3.141}, + // {"happy", true}, + // {"name", "Niels"}, + // {"nothing", nullptr}, + // {"answer", { + // {"everything", 42} + // }}, + // {"list", {1, 0, 2}}, + // {"object", { + // {"currency", "USD"}, + // {"value", 42.99} + // }} + // }; + + TEST(reduceArray, []{ + std::vector v{ 1, 2, 3 }; + return + _::reduceArray(v, [](auto accumulator, auto currentValue, auto currentIndex, auto container) { + return accumulator + "Index: "s + std::to_string(currentIndex) + " = "s + std::to_string(currentValue) + '\n'; + }, "Output: "s); + }); + + TEST(keys, [&]{ + std::map m = { + {"a", 1}, + {"b", 2}, + {"c", 3} + }; + return join(_::keys>(m), ", "); + }); + TEST(keys2, [&]{ + std::map m = { + {"a", 1}, + {"b", 2}, + {"c", 3} + }; + return join(_::keys2(m), ", "); + }); + TEST(reduceObject, [&]{ + std::map m = { + {"a", 1}, + {"b", 2}, + {"c", 3} + }; + return + _::reduceObject(m, []( + auto accumulator, + const auto& currentValue, + const auto& currentKey, + const auto& container) + { + return accumulator + + "Key: "s + + currentKey + + " = "s + + std::to_string(currentValue) + + '\n' + ; + }, "Output: "s); + }); +}