Validate, then map and count

Nucleotide Count
Nucleotide Count in Scala
case class DNA(strand: String) {

  private def findInvalid(strand: String): Option[Either[String, Nothing]] =
    strand
      .find(!"ACTG".contains(_))
      .map(chr => Left(f"invalid nucleotide '$chr'"))

  def nucleotideCounts: Either[String, Map[Char, Int]] =
    findInvalid(strand)
      .getOrElse(Right("ACTG".map(chr => (chr, strand.count(_ == chr))).toMap))
}

This approach starts by defining a private validating method that checks for invalid characters. It does this by calling the find() method on the input String, passing each character in the String to be checked by the contains() method. The underscore (_) wildcard is used to pass in the character, since it doesn't need to be named.

If the ACGT String contains all of the characters, it passes None to the map() method. Otherwise, the first character that is not contained in ACGT is passed as a Some value to map(). If map() receives None, then it returns None from the validating method. If map receives a Some, then map() converts it to a Some Left value which is returned from the method.

The nucleotideCounts() method calls the validating method. If there is any invalid character, then the getOrElse() method returns the Left value from nucleotideCounts(). If getOrElse() receives None, then it maps each character in the ACGT String, passing each into a lambda which uses the count() method to count the occurrences of the character in the input String. The resulting IndexedSeq is converted to a Map by the toMap() method, which is returned from nucleotideCounts(), wrapped as a Right value.

16th Aug 2024 · Found it useful?