Skip to content

Commit 98194f8

Browse files
author
Ioannis Kaliakatsos
committed
Functional reduce algorithm implemented
1 parent bcbe86a commit 98194f8

File tree

4 files changed

+90
-2
lines changed

4 files changed

+90
-2
lines changed

include/set.h

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,36 @@ class set
289289
end(),
290290
std::forward<Callable>(unary_predicate));
291291
}
292-
292+
293+
// Performs the functional `reduce` (fold/accumulate) algorithm, by returning the result of
294+
// accumulating all the values in the vector to an initial value. (non-mutating)
295+
//
296+
// example:
297+
// const fcpp::set<std::string> tokens({ "the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "brown", "dog" });
298+
// const auto sentence = tokens.reduce<std::string>("", [](const std::string& partial, const std::string& token) {
299+
// return partial.length() != 0
300+
// ? partial + " " + token
301+
// : token;
302+
// });
303+
//
304+
// outcome: (a set does not allow multiple entries, and its elements are internally managed, order can vary)
305+
//
306+
// sentence -> std::string("brown dog fox jumps lazy over quick the");
307+
#ifdef CPP17_AVAILABLE
308+
template <typename U, typename Reduce, typename = std::enable_if_t<std::is_invocable_r_v<U, Reduce, U, TKey>>>
309+
#else
310+
template <typename U, typename Reduce>
311+
#endif
312+
U reduce(const U& initial, Reduce&& reduction) const
313+
{
314+
auto result = initial;
315+
for (const auto& x : m_set)
316+
{
317+
result = reduction(result, x);
318+
}
319+
return result;
320+
}
321+
293322
// Performs the functional `filter` algorithm, in which all keys of this instance
294323
// which match the given predicate are kept (mutating)
295324
//

include/vector.h

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,35 @@ class vector
244244
std::forward<Callable>(unary_predicate));
245245
}
246246
#endif
247-
247+
248+
// Performs the functional `reduce` (fold/accumulate) algorithm, by returning the result of
249+
// accumulating all the values in the vector to an initial value. (non-mutating)
250+
//
251+
// example:
252+
// const fcpp::vector<std::string> tokens({ "the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "brown", "dog" });
253+
// const auto sentence = tokens.reduce<std::string>("", [](const std::string& partial, const std::string& token) {
254+
// return partial.length() != 0
255+
// ? partial + " " + token
256+
// : token;
257+
// });
258+
//
259+
// outcome:
260+
// sentence -> std::string("the quick brown fox jumps over the lazy brown dog");
261+
#ifdef CPP17_AVAILABLE
262+
template <typename U, typename Reduce, typename = std::enable_if_t<std::is_invocable_r_v<U, Reduce, U, T>>>
263+
#else
264+
template <typename U, typename Reduce>
265+
#endif
266+
U reduce(const U& initial, Reduce&& reduction) const
267+
{
268+
auto result = initial;
269+
for(const auto &x: m_vector)
270+
{
271+
result = reduction(result, x);
272+
}
273+
return result;
274+
}
275+
248276
// Performs the functional `filter` algorithm, in which all elements of this instance
249277
// which match the given predicate are kept (mutating)
250278
//

tests/set_test.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,17 @@ TEST(SetTest, NoneOf)
333333
EXPECT_FALSE(numbers.none_of([](const int &number) { return number < 6; }));
334334
}
335335

336+
TEST(SetTest, Reduce)
337+
{
338+
const set<std::string> tokens({ "the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "brown", "dog" });
339+
const auto sentence = tokens.reduce(std::string(""), [](const std::string& partial, const std::string& token) {
340+
return partial.length() != 0
341+
? partial + " " + token
342+
: token;
343+
});
344+
EXPECT_EQ("brown dog fox jumps lazy over quick the", sentence);
345+
}
346+
336347
TEST(SetTest, Filter)
337348
{
338349
set<int> numbers({ 1, 3, -5, 2, -1, 9, -4 });

tests/vector_test.cc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,26 @@ TEST(VectorTest, FilteredParallel)
258258
}
259259
#endif
260260

261+
TEST(VectorTest, Reduce)
262+
{
263+
const vector<child> vector_under_test({ child(1), child(3), child(4) });
264+
const auto age_sum = vector_under_test.reduce(0, [](const int& partial_sum, const child& child){
265+
return partial_sum + child.age;
266+
});
267+
EXPECT_EQ(8, age_sum);
268+
}
269+
270+
TEST(VectorTest, ReduceString)
271+
{
272+
const vector<std::string> tokens({ "the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "brown", "dog"});
273+
const auto sentence = tokens.reduce(std::string(""), [](const std::string& partial, const std::string& token) {
274+
return partial.length() != 0
275+
? partial + " " + token
276+
: token;
277+
});
278+
EXPECT_EQ("the quick brown fox jumps over the lazy brown dog", sentence);
279+
}
280+
261281
TEST(VectorTest, Reverse)
262282
{
263283
vector<child> vector_under_test({child(6), child(2), child(9)});

0 commit comments

Comments
 (0)