2

I am trying to figure out how to get the size (num of "levels") of a custom tree-like data structure defined this way:

case class PrefixTreeImpl[K, +V](value: Option[V], prefixTree: Map[K, PrefixTree[K, V]]) extends PrefixTree[K, V]

As you can see it implements the PrefixTree interface (trait actually) which has a size() method amongst others:

def size: Int

I am trying to implement it using foldLeft() Scala method, but I don't really understand how it works with this kind of sophisticated data structures So far I came up with this and got stuck:

override def size: Int = {
  if (prefixTree.isEmpty) 0
  else
    prefixTree.foldLeft(0) {(z, Map[K, PrefixTree[K, V]]()) => z + 1}

}

Obviously it doesn't compile, but I couldn't come up with something else yet.

The way the DS works is:

in: scala>val tree2 = tree1.put(List("one", "two"), 12)

out: PrefixTreeImpl(None,Map(one -> PrefixTreeImpl(None,Map(two -> PrefixTreeImpl(Some(12),Map(tree -> PrefixTreeImpl(Some(123),Map())))))))

Burn_jacks
  • 45
  • 5

1 Answers1

1

It can be done recursively in a next way:

override def size: Int = {
  if(prefixTree.nonEmpty) prefixTree.values.map(_.size + 1).max else 0
}

So next test:

val tree = PrefixTreeImpl(None ,Map("one" -> PrefixTreeImpl(None, Map("two" -> PrefixTreeImpl(Some(12),Map("tree" -> PrefixTreeImpl(Some(123), Map.empty[String, PrefixTree[String, Int]])))))))
    println(tree.size)

produces result: 3

Hope this helps!

Ivan Kurchenko
  • 4,043
  • 1
  • 11
  • 28
  • 2
    This is really close to what I needed, thank you so much! With some slight modifications it works fine – Burn_jacks Mar 28 '20 at 18:52
  • Hey Ivan, I've been thinking about my question for a day or so and came up with another question: how would I treat the same problem if I needed to count the number of stored Option[V] values, not the "levels"? – Burn_jacks Mar 31 '20 at 16:02
  • @Burn_jacks You can try just `sum` instead of `max`: `if(prefixTree.nonEmpty) prefixTree.values.map(_.size + 1).sum else 0` – Ivan Kurchenko Mar 31 '20 at 16:18
  • but in this case the result is going to be '3', while '2' is expected, isn't it? – Burn_jacks Mar 31 '20 at 16:20
  • @Burn_jacks Yes, excuse me. Correct one: ```val count = value.fold(0)(_ => 1) if(prefixTree.nonEmpty) count + prefixTree.values.map(_.size).sum else count ``` – Ivan Kurchenko Mar 31 '20 at 16:27
  • Great job! If you ever find time to explain the mechanics behind or share a link to read about it, I'll be happy to do so. – Burn_jacks Mar 31 '20 at 16:33
  • @Burn_jacks Thanks, but nothing really special there: It's just visiting each node in recursion and if has value, then count it (e.g. as 1), otherwise ignores (e.g. as 0) - and sum up at the end - so this sum will be count of all nodes where value present. – Ivan Kurchenko Mar 31 '20 at 16:36