A Regular Expression to make acronyms with word boundaries and remove characters preceding a word

Viewed 96

Go Version

go version go1.16.7 linux/amd64

Problem

I am going through an Exercise about creating acronyms and I chose to do it with regular expressions.

Some of the test cases given to me are following:

    input:    "Ruby on Rails",
    expected: "ROR"
    
    input:    "GNU Image Manipulation Program",
    expected: "GIMP"

    input:    "Complementary metal-oxide semiconductor",
    expected: "CMOS"

    input:    "Something - I made up from thin air",
    expected: "SIMUFTA"

    input:    "Halley's Comet",
    expected: "HC"

    input:    "The Road _Not_ Taken",
    expected: "TRNT"

The following code is what is able to pass a lot of simple tests where If the First Letter is capital then extract that letter and make an acronym out of it

 Portable Network Graphics -> PNG

Code

// Package acronym creates an acronym based on Capitalized Letters
package acronym

import (
    "regexp"
    "strings"
)

// Abbreviate: creates an acronym for a full form string
func Abbreviate(s string) string {
    re := regexp.MustCompile(`\b[A-Za-z]`)
    abbreviation := strings.Join(re.FindAllString(s, -1), "")
    return strings.ToUpper(abbreviation)
}

The Only tests I am failing are

=== RUN   TestAcronym
    acronym_test.go:11: Acronym test [Halley's Comet], expected [HC], actual [HSC]
    acronym_test.go:11: Acronym test [The Road _Not_ Taken], expected [TRNT], actual [TRT]
--- FAIL: TestAcronym (0.00s)

Regex101 Playground

Link to Playground in Regex 101

Problem

I am unable to figure out how do I compile only the HC for Halley's Comet test case and obtain the N in the The Road _Not_ Taken test case.

One of the reasons I have to keep lower-case characters [a-z] is because of the case Complementary metal-oxide semiconductor and also because of other lower-case characters in certain test cases

I could actually remove such characters such as - or _ before the regexp compilation but I think that would not make my function more generic (rather hack to just past the test)

I wish to know how do I remove the characters ' and _ in order to make the acronym function more robust?

1 Answers

You may use

// Abbreviate: creates an acronym for a full form string
func Abbreviate(s string) string {
    var abbreviation = ""
    re := regexp.MustCompile(`\w'\w|(?:_|\b)([A-Za-z])`)
    for _, match := range re.FindAllStringSubmatch(s, -1) {
        abbreviation = abbreviation + match[1] 
    }
    return strings.ToUpper(abbreviation)
}

See the Go demo. Details:

  • \w'\w - word char, ', word char (to avoid matching ' in between word chars, if you have issues with consequent matches, replace with \b'\w)
  • | - or
  • (?:_|\b) - either _ or word boundary
  • ([A-Za-z]) - Group 1: an ASCII letter (use \p{L} to match any Unicode letter).
Related