summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Morrow <acm@10gen.com>2013-05-09 13:57:03 -0400
committerAndrew Morrow <acm@10gen.com>2013-05-22 16:31:54 -0400
commitc4fdee5db93ed24c5dc07c8b44765a4bde214ae8 (patch)
tree12ff995df5fdab335ffad7ce0b8533f0940e1121
parent6e2d2139e7242b0e1b182a258dfba1e7b6924d8b (diff)
downloadmongo-c4fdee5db93ed24c5dc07c8b44765a4bde214ae8.tar.gz
SERVER-7174 Add a new algorithm to de-duplicate children
-rw-r--r--src/mongo/bson/mutable/algorithm.h62
-rw-r--r--src/mongo/bson/mutable/mutable_bson_algo_test.cpp7
2 files changed, 69 insertions, 0 deletions
diff --git a/src/mongo/bson/mutable/algorithm.h b/src/mongo/bson/mutable/algorithm.h
index 4b3e993a0c4..1f82497abb8 100644
--- a/src/mongo/bson/mutable/algorithm.h
+++ b/src/mongo/bson/mutable/algorithm.h
@@ -111,6 +111,68 @@ namespace mutablebson {
}
}
+ /** Remove any consecutive children that compare as identical according to 'comp'. The
+ * children must be sorted (see sortChildren, above), and the equality comparator here
+ * must be compatible with the comparator used for the sort.
+ */
+ template<typename EqualityComparator>
+ void deduplicateChildren(Element parent, EqualityComparator equal) {
+ Element current = parent.leftChild();
+ while (current.ok()) {
+ Element next = current.rightSibling();
+ if (next.ok() && equal(current, next)) {
+ next.remove();
+ } else {
+ current = next;
+ }
+ }
+ }
+
+ /** A less-than ordering for Elements that compares based on woCompare */
+ class woLess {
+ // TODO: This should possibly derive from std::binary_function.
+ public:
+ woLess(bool considerFieldName = true)
+ : _considerFieldName(considerFieldName) {
+ }
+
+ inline bool operator()(const ConstElement& left, const ConstElement& right) const {
+ return left.compareWithElement(right, _considerFieldName) < 0;
+ }
+ private:
+ const bool _considerFieldName;
+ };
+
+ /** A greater-than ordering for Elements that compares based on woCompare */
+ class woGreater {
+ // TODO: This should possibly derive from std::binary_function.
+ public:
+ woGreater(bool considerFieldName = true)
+ : _considerFieldName(considerFieldName) {
+ }
+
+ inline bool operator()(const ConstElement& left, const ConstElement& right) const {
+ return left.compareWithElement(right, _considerFieldName) > 0;
+ }
+ private:
+ const bool _considerFieldName;
+ };
+
+ /** An equality predicate for elements that compares based on woCompare */
+ class woEqual {
+ // TODO: This should possibly derive from std::binary_function.
+ public:
+ woEqual(bool considerFieldName = true)
+ : _considerFieldName(considerFieldName) {
+ }
+
+ inline bool operator()(const ConstElement& left, const ConstElement& right) const {
+ return left.compareWithElement(right, _considerFieldName) == 0;
+ }
+ private:
+ const bool _considerFieldName;
+ };
+
/** Return the element that is 'n' Elements to the left in the sibling chain of 'element'. */
template<typename ElementType>
ElementType getNthLeftSibling(ElementType element, std::size_t n) {
diff --git a/src/mongo/bson/mutable/mutable_bson_algo_test.cpp b/src/mongo/bson/mutable/mutable_bson_algo_test.cpp
index 8ca7658f4e6..900f6aa8f0a 100644
--- a/src/mongo/bson/mutable/mutable_bson_algo_test.cpp
+++ b/src/mongo/bson/mutable/mutable_bson_algo_test.cpp
@@ -19,6 +19,7 @@
#include "mongo/bson/mutable/document.h"
#include "mongo/bson/mutable/mutable_bson_test_utils.h"
+#include "mongo/db/json.h"
#include "mongo/platform/basic.h"
#include "mongo/unittest/unittest.h"
@@ -258,4 +259,10 @@ namespace {
ASSERT_EQUALS(countChildren(threeChildren), 3u);
}
+ TEST(DeduplicateTest, ManyDuplicates) {
+ Document doc(mongo::fromjson("{ x : [ 1, 2, 2, 3, 3, 3, 4, 4, 4 ] }"));
+ deduplicateChildren(doc.root().leftChild(), woEqual(false));
+ ASSERT_TRUE(checkDoc(doc, mongo::fromjson("{x : [ 1, 2, 3, 4 ]}")));
+ }
+
} // namespace