Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

ToSingular & ToPlural String Extensions

0.00/5 (No votes)
29 Feb 2016 1  
Singular & plural string extensions that leverage .NET Entity Design PluralizationService

Introduction

.NET Entity Design PluralizationService provides methods to construct singular or plural words in a given culture.
This service is available from .NET Framework 4 and above. This implementation of string extension methods are using this service to singularize and pluralize a given word.

The implementation is en-US culture specific. It can be changed to any other language in the PluralizationService static constructor. Another thing that the methods do is to recognize upper case words and singularize and pluralize accordingly.

PluralizationService is not above errors. It pluralizes uncountable nouns (uncountable nouns don't have plurals) and wrongfully pluralize words that their etymology originates from Latin (It pluralizes based on English rules instead of Latin rules). These missteps can be fixed by giving the service a singular-plural word mapping. Obviously, one cannot cover all those missteps so the fix is very personal and limited in scope.

If you're not satisfied with PluralizationService, I suggest that you take a look at Humanizer Library. You can Nuget Humanizer or just cannibalize the plural & singular from the library inflections implementation.

using System;
using System.Data.Entity.Design.PluralizationServices;
using System.Globalization;

namespace Extensions
{
    public static class StringExtensions
    {
        private static readonly PluralizationService service = 
            PluralizationService.CreateService(CultureInfo.GetCultureInfo("en-US"));

        static StringExtensions()
        {
            var mapping = (ICustomPluralizationMapping)service;
            mapping.AddWord("Cactus", "Cacti");
            mapping.AddWord("cactus", "cacti");
            mapping.AddWord("Die", "Dice");
            mapping.AddWord("die", "dice");
            mapping.AddWord("Equipment", "Equipment");
            mapping.AddWord("equipment", "equipment");
            mapping.AddWord("Money", "Money");
            mapping.AddWord("money", "money");
            mapping.AddWord("Nucleus", "Nuclei");
            mapping.AddWord("nucleus", "nuclei");
            mapping.AddWord("Quiz", "Quizzes");
            mapping.AddWord("quiz", "quizzes");
            mapping.AddWord("Shoe", "Shoes");
            mapping.AddWord("shoe", "shoes");
            mapping.AddWord("Syllabus", "Syllabi");
            mapping.AddWord("syllabus", "syllabi");
            mapping.AddWord("Testis", "Testes");
            mapping.AddWord("testis", "testes");
            mapping.AddWord("Virus", "Viruses");
            mapping.AddWord("virus", "viruses");
            mapping.AddWord("Water", "Water");
            mapping.AddWord("water", "water");
        }

        public static string ToSingular(this string word)
        {
            if (word == null)
                throw new ArgumentNullException("word");

            bool isUpperWord = (string.Compare(word, word.ToUpper(), false) == 0);
            if (isUpperWord)
            {
                string lowerWord = word.ToLower();
                return (service.IsSingular(lowerWord) ? lowerWord : 
                    service.Singularize(lowerWord)).ToUpper();
            }

            return (service.IsSingular(word) ? word : service.Singularize(word));
        }

        public static string ToPlural(this string word)
        {
            if (word == null)
                throw new ArgumentNullException("word");

            bool isUpperWord = (string.Compare(word, word.ToUpper(), false) == 0);
            if (isUpperWord)
            {
                string lowerWord = word.ToLower();
                return (service.IsPlural(lowerWord) ? lowerWord : 
                    service.Pluralize(lowerWord)).ToUpper();
            }

            return (service.IsPlural(word) ? word : service.Pluralize(word));
        }
    }
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here