Pluralize.swift
Pluralize.swift
After learning the Swift programming language, I realized that there isn't an existing Swift extension that converts a singular word to its plural form. I decided to write Pluralize.swift.

        

          import Pluralize

          "Person".pluralize()
          // People

          "Wolf".pluralize(count: 1)
          // Wolf

          "Person".pluralize(with: "Persons")
          // Persons
        
      

The implementation of the String extension is based from Ruby's ActiveSupport::Inflector#inflections. An array of (RegEx) rules is prepared first then each rule is tested against the word to be pluralized. Pluralize.swift makes use of NSRegularExpression and the stringByReplacingMatchesInString method for its replace operations.

        

          rule("$", with:"$1s")
          rule("s$", with:"$1ses")
          rule("(r|l|b)y$", with:"$1ies")
          rule("x$", with:"$1xes")
          rule("(sh|zz|ss)$", with:"$1es")
          rule("(ax)is", with: "$1es")
          rule("(cact|nucle|alumn|bacill|fung|radi|stimul|syllab)us$", with:"$1i")
          rule("(corp)us$", with:"$1ora")
          rule("sis$", with:"$1ses")
          rule("ch$", with:"$1ches")
          rule("o$", with:"$1os")
          rule("(buffal|carg|mosquit|torped|zer|vet|her|ech)o$", with:"$1oes")

          unchanging("sheep")
          unchanging("deer")
          unchanging("moose")
          unchanging("swine")
          unchanging("bison")
          unchanging("corps")
          unchanging("means")
          unchanging("series")
          unchanging("scissors")
          unchanging("species")
        
      

Extensions in Swift are easy to write. I added a type method called pluralize that accepts 2 optional parameters: the count and the replacement String.

        

        extension String {
            public func pluralize(count: Int = 2, with: String = "") -> String {
                if count == 1 {
                    return self
                } else {
                    if countElements(with) != 0 {
                        return with
                    } else {
                        return Pluralize.apply(self)
                    }
                }
            }
        }
        
      

Finally, I added a couple of type methods to allow the addition of custom rules. These methods simply update the sharedInstance singleton with new rules.

        

        public class func rule(rule: String, with template: String) {
            sharedInstance.rule(rule, with: template)
        }
        
        public class func uncountable(word: String) {
            sharedInstance.uncountable(word)
        }
        
        public class func unchanging(word: String) {
            sharedInstance.unchanging(word)
        }

        ...

        public class var sharedInstance : Pluralize {
            struct Static {
                static var onceToken : dispatch_once_t = 0
                static var instance : Pluralize? = nil
            }
            
            dispatch_once(&Static.onceToken) {
                Static.instance = Pluralize()
            }
            
            return Static.instance!
        }
        
      

This allows users to do the following:

        

        Pluralize.rule("(p)erson$", with: "$1ersons")

        ...

        "Person".pluralize()
        // Persons
        "Spokesperson".pluralize()
        // Spokespersons
        
      

For more information, click here.