[libgee] Add some more query operations for Traversable<G>



commit ed30714507e6099c5f56bd7469706e550a68bda8
Author: Rodrigo Moya <rodrigo gnome org>
Date:   Thu Dec 29 01:05:00 2016 +0100

    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

 gee/traversable.vala      |  112 +++++++++++++++++++++++++++++++++++++++++++++
 tests/testcollection.vala |   62 +++++++++++++++++++++++++
 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;
+               }
+       }
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]