From e430c56ed1b7cd369a7a0fefe1f99608f993dd36 Mon Sep 17 00:00:00 2001 From: Jean Privat Date: Thu, 15 Jun 2017 15:37:18 -0400 Subject: [PATCH] poset: add lookup services in Map to search using keys inhierarchies. 3 main methods: * `Map::lookup_all_values` collect all values of the greaters of an element * `Map::lookup_values` collect only the values of the most specific greaters of an element * `MultiHashMap::lookup_joined_values` collect and join the values of the most specific greaters of an element Since many models entities in nitc are in some poset, these services could be used to add and retrieve metadata while automatically taking in account inheritance or importation. Signed-off-by: Jean Privat --- lib/more_collections.nit | 30 +++++++++++++++++ lib/poset.nit | 81 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) diff --git a/lib/more_collections.nit b/lib/more_collections.nit index 81688d9..184419c 100644 --- a/lib/more_collections.nit +++ b/lib/more_collections.nit @@ -16,6 +16,7 @@ module more_collections is serialize import serialization +import poset # Simple way to store an `HashMap[K, Array[V]]` # @@ -102,6 +103,35 @@ class MultiHashMap[K, V] if x.is_empty then keys.remove(k) end end + + # Search the values in `pe.greaters` from the most smaller elements that have a value. + # + # Elements without values are ignored. + # + # Basically, values defined in nearest greater elements of `pe` are inherited. + # + # ~~~ + # var pos = new POSet[String] + # pos.add_chain(["E", "D", "C", "B", "A"]) + # pos.add_chain(["D", "X", "B"]) + # + # var map = new MultiHashMap[String, String] + # map["A"].append(["a", "1"]) + # map["C"].append(["c", "2"]) + # map["X"].append(["x", "2"]) + # map["E"].add "e" + # + # assert map.lookup_joined_values(pos["B"]).has_exactly(["a", "1"]) + # assert map.lookup_joined_values(pos["C"]).has_exactly(["c", "2"]) + # assert map.lookup_joined_values(pos["D"]).has_exactly(["c", "x", "2"]) + # ~~~ + fun lookup_joined_values(pe: POSetElement[K]): Set[V] + do + var res = new Set[V] + for k in pe.poset.select_smallest(filter_keys(pe.greaters)) do res.add_all self[k] + return res + + end end # Simple way to store an `HashMap[K1, HashMap[K2, V]]` diff --git a/lib/poset.nit b/lib/poset.nit index 98205ac..767b27d 100644 --- a/lib/poset.nit +++ b/lib/poset.nit @@ -729,3 +729,84 @@ class POSetElement[E] end end end + +redef class MapRead[K, V] + # Return all elements of `keys` that have a value. + # + # ~~~ + # var map = new Map[String, String] + # map["A"] = "a" + # map["B"] = "b" + # map["C"] = "c" + # + # assert map.filter_keys(["B"]) == ["B"] + # assert map.filter_keys(["A", "Z", "C"]) == ["A", "C"] + # assert map.filter_keys(["X", "Y", "Z"]).is_empty + # ~~~ + # + # `has_key` is used to filter. + fun filter_keys(keys: Collection[nullable Object]): Array[K] + do + var res = new Array[K] + for e in keys do + if has_key(e) then res.add e + end + return res + end + + # Search all the values in `pe.greaters`. + # + # Elements without values are ignored. + # + # Basically, values defined in all greater elements of `pe` are inherited. + # + # ~~~ + # var pos = new POSet[String] + # pos.add_chain(["E", "D", "C", "B", "A"]) + # pos.add_chain(["D", "X", "B"]) + # + # var map = new HashMap[String, String] + # map["A"] = "a" + # map["C"] = "c" + # map["X"] = "x" + # map["E"] = "e" + # + # assert map.lookup_all_values(pos["B"]).has_exactly(["a"]) + # assert map.lookup_all_values(pos["C"]).has_exactly(["a", "c"]) + # assert map.lookup_all_values(pos["D"]).has_exactly(["a", "c", "x"]) + # ~~~ + fun lookup_all_values(pe: POSetElement[K]): Set[V] + do + var res = new Set[V] + for k in filter_keys(pe.greaters) do res.add self[k] + return res + end + + # Combine the values in `pe.greaters` from the most smaller elements that have a value. + # + # Elements without values are ignored. + # + # Basically, values defined in nearest greater elements of `pe` are inherited. + # + # ~~~ + # var pos = new POSet[String] + # pos.add_chain(["E", "D", "C", "B", "A"]) + # pos.add_chain(["D", "X", "B"]) + # + # var map = new HashMap[String, String] + # map["A"] = "a" + # map["C"] = "c" + # map["X"] = "x" + # map["E"] = "e" + # + # assert map.lookup_values(pos["B"]).has_exactly(["a"]) + # assert map.lookup_values(pos["C"]).has_exactly(["c"]) + # assert map.lookup_values(pos["D"]).has_exactly(["c", "x"]) + # ~~~ + fun lookup_values(pe: POSetElement[K]): Set[V] + do + var res = new Set[V] + for k in pe.poset.select_smallest(filter_keys(pe.greaters)) do res.add self[k] + return res + end +end -- 1.7.9.5