1 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors. 2 // https://github.com/Dobiasd/FunctionalPlus 3 // Distributed under the Boost Software License, Version 1.0. 4 // (See accompanying file LICENSE_1_0.txt or copy at 5 // http://www.boost.org/LICENSE_1_0.txt) 6 7 #include <doctest/doctest.h> 8 #include <fplus/fplus.hpp> 9 #include <vector> 10 11 namespace { 12 auto is_even = [](auto value) __anon356105bb0202(auto value) 13 { 14 return (value % 2 == 0); 15 }; 16 17 auto is_even_size_t = [](auto value) __anon356105bb0302(auto value) 18 { 19 return ( value % 2 == 0 ); 20 }; 21 22 auto accept_with_index = [](std::size_t index, auto value) __anon356105bb0402(std::size_t index, auto value) 23 { 24 return ( index % 2 == 0 ) && ( value >= 10 ); 25 }; 26 27 typedef std::vector<int> IntVector; 28 typedef std::vector<IntVector> IntVectors; 29 } 30 31 TEST_CASE("filter_test - keep_if") 32 { 33 const std::vector<int> v = { 1, 2, 3, 2, 4, 5 }; 34 auto result = fplus::keep_if(is_even, v); 35 REQUIRE_EQ(result, std::vector<int>({2, 2, 4})); 36 37 const auto keep_evens = fplus::bind_1st_of_2( 38 fplus::keep_if<decltype(is_even), const IntVector&>, is_even); 39 40 REQUIRE_EQ( 41 fplus::transform(keep_evens, IntVectors({{1,3,4},{1,2}})), 42 IntVectors({{4},{2}})); 43 } 44 45 TEST_CASE("filter_test - keep_if_r_value") 46 { 47 auto result = fplus::keep_if(is_even, std::vector<int>({1,2,3,2,4,5})); 48 REQUIRE_EQ(result, std::vector<int>({2, 2, 4})); 49 } 50 51 TEST_CASE("filter_test - drop_if") 52 { 53 const std::vector<int> v = { 1, 2, 3, 2, 4, 5 }; 54 auto result = fplus::drop_if(is_even, v); 55 REQUIRE_EQ(result, std::vector<int>({1, 3, 5})); 56 } 57 58 TEST_CASE("filter_test - without") 59 { 60 using namespace fplus; 61 typedef std::vector<int> Ints; 62 REQUIRE_EQ(without(1, Ints({1,2,3})), Ints({2,3})); 63 REQUIRE_EQ(without(5, Ints({1,2,3})), Ints({1,2,3})); 64 REQUIRE_EQ(without(5, Ints({})), Ints({})); 65 } 66 67 TEST_CASE("filter_test - keep_if_with_idx") 68 { 69 const std::vector<int> v = { 1, 20, 30, 4, 50, 60, 7 }; 70 auto result = fplus::keep_if_with_idx(accept_with_index, v); 71 REQUIRE_EQ(result, std::vector<int>({30, 50})); 72 } 73 74 TEST_CASE("filter_test - drop_if_with_idx") 75 { 76 const std::vector<int> v = { 1, 20, 30, 4, 50, 60, 7 }; 77 auto result = fplus::drop_if_with_idx(accept_with_index, v); 78 REQUIRE_EQ(result, std::vector<int>({1, 20, 4, 60, 7})); 79 } 80 81 TEST_CASE("filter_test - keep_by_idx") 82 { 83 const std::vector<int> v = { 11, 17, 3, 8, 49, 6 }; 84 auto result = fplus::keep_by_idx(is_even_size_t, v); 85 REQUIRE_EQ(result, std::vector<int>({11, 3, 49})); 86 auto result_rvalue = fplus::keep_by_idx(is_even_size_t, std::vector<int>({ 11, 17, 3, 8, 49, 6 })); 87 REQUIRE_EQ(result_rvalue, std::vector<int>({11, 3, 49})); 88 89 const std::vector<std::string> v_strs = { "foo", "bar" }; 90 const auto result_kept_all_strs = fplus::keep_by_idx(fplus::always<std::size_t>(true), v_strs); 91 REQUIRE_EQ(result_kept_all_strs, v_strs); 92 const auto result_kept_all_strs_r_value = 93 fplus::keep_by_idx(fplus::always<std::size_t>(true), std::vector<std::string>({ "foo", "bar" })); 94 REQUIRE_EQ(result_kept_all_strs_r_value, std::vector<std::string>({ "foo", "bar" })); 95 } 96 97 TEST_CASE("filter_test - drop_by_idx") 98 { 99 const std::vector<int> v = { 11, 17, 3, 8, 49, 6 }; 100 auto result = fplus::drop_by_idx(is_even_size_t, v); 101 REQUIRE_EQ(result, std::vector<int>({17, 8, 6})); 102 } 103 104 TEST_CASE("filter_test - keep_idxs") 105 { 106 const std::vector<int> v = { 1, 2, 3, 4, 5, 6, 7 }; 107 const std::vector<std::size_t> indices = { 2, 5 }; 108 auto result = fplus::keep_idxs(indices, v); 109 REQUIRE_EQ(result, std::vector<int>({3, 6})); 110 } 111 112 TEST_CASE("filter_test - drop_idx") 113 { 114 const std::vector<int> v = { 1, 2, 3, 4, 5, 6, 7 }; 115 auto result = fplus::drop_idx(2, v); 116 REQUIRE_EQ(result, std::vector<int>({1, 2, 4, 5, 6, 7})); 117 } 118 119 TEST_CASE("filter_test - drop_idxs") 120 { 121 const std::vector<int> v = { 1, 2, 3, 4, 5, 6, 7 }; 122 const std::vector<std::size_t> indices = { 2, 5 }; 123 auto result = fplus::drop_idxs(indices, v); 124 REQUIRE_EQ(result, std::vector<int>({1, 2, 4, 5, 7})); 125 } 126 127 TEST_CASE("filter_test - justs") 128 { 129 using fplus::maybe; 130 using fplus::just; 131 using fplus::nothing; 132 133 const std::vector<maybe<int>> v = { just(1), nothing<int>(), just(2) }; 134 auto result = fplus::justs(v); 135 REQUIRE_EQ(result, std::vector<int>({1, 2})); 136 } 137 138 TEST_CASE("filter_test - oks") 139 { 140 using fplus::ok; 141 using fplus::error; 142 const std::vector<fplus::result<int, std::string>> v = { ok<int, std::string>(1), 143 error<int>(std::string("abc")), 144 ok<int, std::string>(2) }; 145 auto result = fplus::oks(v); 146 REQUIRE_EQ(result, std::vector<int>({1, 2})); 147 } 148 149 TEST_CASE("filter_test - errors") 150 { 151 using fplus::ok; 152 using fplus::error; 153 const std::vector<fplus::result<int, std::string>> v = { ok<int, std::string>(1), 154 error<int>(std::string("abc")), 155 ok<int, std::string>(2) }; 156 auto result = fplus::errors(v); 157 REQUIRE_EQ(result, std::vector<std::string>({"abc"})); 158 } 159 160 TEST_CASE("filter_test - trim_left") 161 { 162 const std::vector<int> v = { 0, 0, 0, 5, 6, 7, 8, 6, 4 }; 163 auto result = fplus::trim_left(0, v); 164 REQUIRE_EQ(result, std::vector<int>({5, 6, 7, 8, 6, 4})); 165 } 166 167 TEST_CASE("filter_test - trim_token_left") 168 { 169 const std::vector<int> v = { 0, 1, 2, 0, 1, 2, 7, 5, 9 }; 170 const std::vector<int> token = { 0, 1, 2 }; 171 auto result = fplus::trim_token_left(token, v); 172 REQUIRE_EQ(result, std::vector<int>({7, 5, 9})); 173 } 174 175 TEST_CASE("filter_test - trim_right_by") 176 { 177 const std::vector<int> v = { 0, 2, 4, 5, 6, 7, 8, 6, 4 }; 178 auto result = fplus::trim_right_by(is_even, v); 179 REQUIRE_EQ(result, std::vector<int>({0, 2, 4, 5, 6, 7})); 180 } 181 182 TEST_CASE("filter_test - trim_right_by_trims_all") 183 { 184 const std::vector<int> v = { 4, 8 }; 185 auto result = fplus::trim_right_by(is_even, v); 186 REQUIRE(result.empty()); 187 } 188 189 TEST_CASE("filter_test - trim_right") 190 { 191 const std::vector<int> v = { 0, 2, 4, 5, 6, 7, 8, 4, 4 }; 192 auto result = fplus::trim_right(4, v); 193 REQUIRE_EQ(result, std::vector<int>({0, 2, 4, 5, 6, 7, 8})); 194 } 195 196 TEST_CASE("filter_test - trim_token_right") 197 { 198 const std::vector<int> v = { 7, 5, 9, 0, 1, 2, 0, 1, 2 }; 199 const std::vector<int> token = { 0, 1, 2 }; 200 auto result = fplus::trim_token_right(token, v); 201 REQUIRE_EQ(result, std::vector<int>({7, 5, 9})); 202 } 203 204 TEST_CASE("filter_test - trim_by") 205 { 206 const std::vector<int> v = { 0, 2, 4, 5, 6, 7, 8, 6, 4 }; 207 auto result = fplus::trim_by(is_even, v); 208 REQUIRE_EQ(result, std::vector<int>({5, 6, 7})); 209 } 210 211 TEST_CASE("filter_test - trim") 212 { 213 const std::vector<int> v = { 0, 2, 4, 5, 6, 7, 8, 0, 0 }; 214 auto result = fplus::trim(0, v); 215 REQUIRE_EQ(result, std::vector<int>({2, 4, 5, 6, 7, 8})); 216 } 217 218 TEST_CASE("filter_test - trim_token") 219 { 220 const std::vector<int> v = { 0, 1, 7, 8, 9, 0, 1 }; 221 const std::vector<int> token = { 0, 1 }; 222 auto result = fplus::trim_token(token, v); 223 REQUIRE_EQ(result, std::vector<int>({7, 8, 9})); 224 } 225 226 TEST_CASE("filter_test - adjacent_keep_snd_if") 227 { 228 const std::vector<int> v = { 0, 1, 7, 8, 9, 0, 1 }; 229 REQUIRE_EQ(fplus::adjacent_keep_snd_if(std::greater<>(), v), std::vector<int>({0,0})); 230 REQUIRE_EQ(fplus::adjacent_keep_snd_if(std::less<int>(), v), std::vector<int>({0,1,7,8,9,1})); 231 } 232 233 TEST_CASE("filter_test - adjacent_drop_snd_if") 234 { 235 const std::vector<int> v = { 0, 1, 7, 8, 9, 0, 1 }; 236 REQUIRE_EQ(fplus::adjacent_drop_snd_if(std::less<>(), v), std::vector<int>({0,0})); 237 REQUIRE_EQ(fplus::adjacent_drop_snd_if(std::greater<int>(), v), std::vector<int>({0,1,7,8,9,1})); 238 } 239 240 TEST_CASE("filter_test - adjacent_drop_fst_if") 241 { 242 const std::vector<int> v = { 0, 1, 7, 8, 9, 0, 1 }; 243 REQUIRE_EQ(fplus::adjacent_drop_fst_if(std::less<>(), v), std::vector<int>({9,1})); 244 REQUIRE_EQ(fplus::adjacent_drop_fst_if(std::greater<int>(), v), std::vector<int>({0,1,7,8,0,1})); 245 } 246 247 TEST_CASE("filter_test - adjacent_keep_fst_if") 248 { 249 const std::vector<int> v = { 0, 1, 7, 8, 9, 0, 1 }; 250 REQUIRE_EQ(fplus::adjacent_keep_fst_if(std::greater<>(), v), std::vector<int>({9,1})); 251 REQUIRE_EQ(fplus::adjacent_keep_fst_if(std::less<int>(), v), std::vector<int>({0,1,7,8,0,1})); 252 } 253