patkua@work

Adding toSortedSet on Seq in Scala

We recently wanted to do some transformation on our small XML document in order to present some information on it. In this example, our example looks like this:

<basket>
  <item cost=".99" discountCode="A5">Last year's red Christmas baubles</item>
  <item cost=".10" discountCode="A5">Halloween lamps</item>
  <item cost="101.99" >Pine Tree</item>
  <item cost="20" discountCode="B2">Gold star</item>
</basket>

It’s a pretty simple structure with some simple rules. A basket can contain one or more items. Each item has:

The task we had was to display a list of human-readable discounts that had been applied to this particular basket. In the example given about the discount codes are A5 and B2.

We have a very simple list of known discounts, and can implement a simple conversion function:

object Discounts {
  def displayString(code : String): String = {
    code match  {
      case "A5" => "Reduced to clear"
      case "B2" => "Pre-Christmas offer"
    }
  }
}

We already had a class that wrapped this small XML document, creating a cached field for the item nodes.

class Basket(val rootNode: Node) {
  private lazy val items = (rootNode \ "item");
}

We can then apply a series of functions to convert the items:

class Basket(val rootNode: Node) {
  private lazy val items = (rootNode \ "item");

  lazy val discountsApplied = 
    items.map(item => item.attribute("discountCode")
         .map(attribute => displayString(attribute.text)))
         .flatten
}

The above code pulls out all the “discountCode” attributes, and applies a conversion function to convert them to human-readable form. Since item.attribute returns an Option, we use flatten to get rid of elements that are essentially null.

Unfortunately, while there is a toSet method, and a list, there isn’t a great way to do both inbuilt. However, by constructing a TreeSet (a sorted set), we can append all the results and get the same effect. We end up with the following:

class Basket(val rootNode: Node) {
  private lazy val items = (rootNode \ "item");

  lazy val discountsApplied = sortedUniqueSet(
    items.map(item => item.attribute("discountCode")
         .map(attribute => displayString(attribute.text)))
         .flatten)

  private def sortedUniqueSet(sequence: Seq[String]) = {
    TreeSet.empty[String] ++ sequence
  }
}
Exit mobile version