diff --git a/tdutils/td/utils/misc.h b/tdutils/td/utils/misc.h index 614b5aa1..c49bcc5d 100644 --- a/tdutils/td/utils/misc.h +++ b/tdutils/td/utils/misc.h @@ -53,10 +53,10 @@ string implode(const vector &v, char delimiter = ' '); namespace detail { -template +template struct transform_helper { template - auto transform(const T &v, const Func &f) { + auto transform(const V &v, const Func &f) { vector result; result.reserve(v.size()); for (auto &x : v) { @@ -66,7 +66,7 @@ struct transform_helper { } template - auto transform(T &&v, const Func &f) { + auto transform(V &&v, const Func &f) { vector result; result.reserve(v.size()); for (auto &x : v) { @@ -78,13 +78,13 @@ struct transform_helper { } // namespace detail -template -auto transform(T &&v, const Func &f) { - return detail::transform_helper>().transform(std::forward(v), f); +template +auto transform(V &&v, const Func &f) { + return detail::transform_helper>().transform(std::forward(v), f); } -template -void remove_if(T &v, const Func &f) { +template +void remove_if(V &v, const Func &f) { size_t i = 0; while (i != v.size() && !f(v[i])) { i++; @@ -103,9 +103,29 @@ void remove_if(T &v, const Func &f) { } template -bool contains(const V &v, const T &elem) { +bool remove(V &v, const T &value) { + size_t i = 0; + while (i != v.size() && v[i] != value) { + i++; + } + if (i == v.size()) { + return false; + } + + size_t j = i; + while (++i != v.size()) { + if (v[i] != value) { + v[j++] = std::move(v[i]); + } + } + v.erase(v.begin() + j, v.end()); + return true; +} + +template +bool contains(const V &v, const T &value) { for (auto &x : v) { - if (x == elem) { + if (x == value) { return true; } } diff --git a/tdutils/test/misc.cpp b/tdutils/test/misc.cpp index 0f2e30e0..1c5670e2 100644 --- a/tdutils/test/misc.cpp +++ b/tdutils/test/misc.cpp @@ -268,6 +268,31 @@ TEST(Misc, remove_if) { test_remove_if(v, none, v); } +static void test_remove(vector v, int value, vector expected) { + bool is_found = expected != v; + ASSERT_EQ(is_found, td::remove(v, value)); + if (expected != v) { + LOG(FATAL) << "Receive " << v << ", expected " << expected << " in remove"; + } +} + +TEST(Misc, remove) { + vector v{1, 2, 3, 4, 5, 6}; + test_remove(v, 0, {1, 2, 3, 4, 5, 6}); + test_remove(v, 1, {2, 3, 4, 5, 6}); + test_remove(v, 2, {1, 3, 4, 5, 6}); + test_remove(v, 3, {1, 2, 4, 5, 6}); + test_remove(v, 4, {1, 2, 3, 5, 6}); + test_remove(v, 5, {1, 2, 3, 4, 6}); + test_remove(v, 6, {1, 2, 3, 4, 5}); + test_remove(v, 7, {1, 2, 3, 4, 5, 6}); + + v.clear(); + test_remove(v, -1, v); + test_remove(v, 0, v); + test_remove(v, 1, v); +} + TEST(Misc, contains) { td::vector v{1, 3, 5, 7, 4, 2}; for (int i = -10; i < 20; i++) {