summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRodrigo Moya <rodrigo@gnome.org>2016-12-29 01:05:00 +0100
committerRico Tzschichholz <ricotz@ubuntu.com>2017-01-17 14:19:03 +0100
commited30714507e6099c5f56bd7469706e550a68bda8 (patch)
tree9df2860bb850f06ac1ce8b18c9ebcccada7e4b66
parent391c7fcd45c3f83aef009a70ac45a97a50d839ce (diff)
downloadlibgee-ed30714507e6099c5f56bd7469706e550a68bda8.tar.gz
Add some more query operations for Traversable<G>
* first_match (Predicate<G>) returns the first item that matches * any_match (Predicate<G>) checks if any element matches * all_match (Predicate<G>) checks if all elements match * max/min returns max/min value * order_by to perform ordering on any Traversable https://bugzilla.gnome.org/show_bug.cgi?id=776558
-rw-r--r--gee/traversable.vala112
-rw-r--r--tests/testcollection.vala62
2 files changed, 174 insertions, 0 deletions
diff --git a/gee/traversable.vala b/gee/traversable.vala
index 77ce6ea..bc6ae1d 100644
--- a/gee/traversable.vala
+++ b/gee/traversable.vala
@@ -446,6 +446,118 @@ public interface Gee.Traversable<G> : Object {
}
}
+ /**
+ * Returns the first element that matches a given condition
+ *
+ * @param pred Predicate to be called to check for matches
+ * @return The first element that matches or null
+ * @since 0.18.2
+ */
+ [CCode (ordering = 10)]
+ public virtual G? first_match (owned Predicate<G> pred) {
+ G? result = null;
+ this.foreach ((item) => {
+ if (pred (item)) {
+ result = item;
+ return false;
+ }
+ return true;
+ });
+ return (owned) result;
+ }
+
+ /**
+ * Returns whether any element matches the given predicate.
+ *
+ * This is similar to @first_match, with the difference that it
+ * just returns whether there is a match or not, not the value
+ * of the match.
+ *
+ * @param pred Predicate to be called to check for matches
+ * @return Whether there was a match or not
+ * @since 0.18.2
+ */
+ [CCode (ordering = 11)]
+ public virtual bool any_match (owned Predicate<G> pred) {
+ return this.first_match (pred) != null;
+ }
+
+ /**
+ * Checks whether all elements match the given predicate.
+ *
+ * @param pred Predicate to be called to check for matches
+ * @return Whether all elements match or not
+ * @since 0.18.2
+ */
+ [CCode (ordering = 12)]
+ public virtual bool all_match (owned Predicate<G> pred) {
+ bool result = true;
+ this.foreach ((item) => {
+ if (!pred (item)) {
+ result = false;
+ return false;
+ }
+ return true;
+ });
+ return result;
+ }
+
+ /**
+ * Returns the item in the sequence that contains the max value
+ * based on the given compare function.
+ *
+ * @param compare Function to be called for comparisons
+ * @return The item containing the max value.
+ * @since 0.18.2
+ */
+ [CCode (ordering = 13)]
+ public virtual G max (owned CompareDataFunc<G> compare) {
+ G max_value = null;
+ this.foreach ((item) => {
+ if (max_value == null || compare (max_value, item) > 0) {
+ max_value = item;
+ }
+ return true;
+ });
+ return max_value;
+ }
+
+ /**
+ * Returns the item in the sequence that contains the min value
+ * based on the given compare function.
+ *
+ * @param compare Function to be called for comparisons
+ * @return The item containing the min value.
+ * @since 0.18.2
+ */
+ [CCode (ordering = 14)]
+ public virtual G min (owned CompareDataFunc<G> compare) {
+ G min_value = null;
+ this.foreach ((item) => {
+ if (min_value == null || compare (min_value, item) < 0) {
+ min_value = item;
+ }
+ return true;
+ });
+ return min_value;
+ }
+
+ /**
+ * Returns a new iterator containing the elements in the source
+ * ordered as specified by the comparison function.
+ *
+ * @param compare Comparison function
+ * @return A new iterator with the source elements sorted.
+ * @since 0.18.2
+ */
+ [CCode (ordering = 15)]
+ public virtual Iterator<G> order_by (owned CompareDataFunc<G>? compare = null) {
+ ArrayList<G> result = new ArrayList<G> ();
+ this.foreach ((item) => result.add (item));
+ result.sort (compare);
+ return result.iterator ();
+ }
+
public enum Stream {
YIELD,
CONTINUE,
diff --git a/tests/testcollection.vala b/tests/testcollection.vala
index 268724a..819e130 100644
--- a/tests/testcollection.vala
+++ b/tests/testcollection.vala
@@ -51,6 +51,11 @@ public abstract class CollectionTests : Gee.TestCase {
add_test ("[Collection] scan", test_scan);
add_test ("[Collection] filter", test_filter);
add_test ("[Collection] chop", test_chop);
+ add_test ("[Collection] first_match", test_first_match);
+ add_test ("[Collection] any_match", test_any_match);
+ add_test ("[Collection] all_match", test_all_match);
+ add_test ("[Collection] max_min", test_max_min);
+ add_test ("[Collection] order_by", test_order_by);
}
protected Collection<string> test_collection;
@@ -1197,5 +1202,62 @@ public abstract class CollectionTests : Gee.TestCase {
assert (!iter.next ());
assert (iter2.next ());
}
+
+ public void test_first_match () {
+ assert (test_collection.add ("one"));
+ assert (test_collection.add ("two"));
+ assert (test_collection.add ("three"));
+
+ assert (test_collection.first_match ((x) => x == "one") == "one");
+ assert (test_collection.first_match ((x) => x == "two") == "two");
+ assert (test_collection.first_match ((x) => x == "three") == "three");
+ assert (test_collection.first_match ((x) => x == "four") == null);
+ }
+
+ public void test_any_match () {
+ assert (test_collection.add ("one"));
+ assert (test_collection.add ("two"));
+ assert (test_collection.add ("three"));
+
+ assert (test_collection.any_match ((x) => x == "one"));
+ assert (test_collection.any_match ((x) => x == "two"));
+ assert (test_collection.any_match ((x) => x == "three"));
+ assert (!test_collection.any_match ((x) => x == "four"));
+ }
+
+ public void test_all_match () {
+ assert (test_collection.add ("one"));
+ assert (test_collection.all_match ((x) => x == "one"));
+
+ assert (test_collection.add ("two"));
+ assert (!test_collection.all_match ((x) => x == "one"));
+ }
+
+ public void test_max_min () {
+ assert (test_collection.add ("one"));
+ assert (test_collection.add ("two"));
+ assert (test_collection.add ("three"));
+
+ assert (test_collection.max ((a, b) => strcmp (a, b)) == "one");
+ assert (test_collection.min ((a, b) => strcmp (a, b)) == "two");
+ }
+
+ public void test_order_by () {
+ assert (test_collection.add ("one"));
+ assert (test_collection.add ("two"));
+ assert (test_collection.add ("three"));
+
+ var sorted_collection = test_collection.order_by ((a, b) => strcmp (a, b));
+
+ string previous_item = null;
+ while (sorted_collection.next ()) {
+ var item = sorted_collection.get ();
+ if (previous_item != null) {
+ assert (strcmp (previous_item, item) <= 0);
+ }
+
+ previous_item = item;
+ }
+ }
}