string.KeepOnly

Often when working with string data you need to strip away certain characters, filtering out some kernel that you’re interested in. For example, you may want to compare two phone numbers to see if they contain the same digits but you don’t care if the formatting is different. Or you may need to strip punctuation, or keep only letters, etc.

Normally when you encounter a situation like this, we pull out a for loop and get the job done. But if you solve any one of the above scenarios directly with an off-the-cuff for loop, you’ve just missed your chance to solve the more generic problem of keeping only certain types of characters in a string. And in C#, this is a solution we can easily package into an extension method:

public static string KeepOnly(this string text, Func<char, bool> filter)
{
    if (text == null)
        return null;

    var sb = new StringBuilder();

    foreach (var c in text)
    {
        if (filter(c))
            sb.Append(c);
    }

    return sb.ToString();
}

Armed with this simple method, we can now strip a string of anything but digits like this:

var digits = "(123) 456-7890".KeepOnly(c => char.IsDigit(c));

Which can be packaged into an even more easy-to-read extension:

public static string KeepOnlyDigits(this string text)
{
    return text.KeepOnly(c => char.IsDigit(c));
}

Which can be used like this:

var digits = "(123) 456-7890".KeepOnlyDigits();

Which, I guarantee you, is a thousand times more readable and reusable than an inline for loop.

In my .NET utility library I’ve defined a bunch of methods like this for common string filtering. Here’s the entire class:

using System;
using System.Text;
using System.Linq;

namespace Cooper.Extensions
{
    public static class StringKeepOnlyExtensions
    {
        public static string KeepOnly(this string text, Func<char, bool> filter)
        {
            if (text.IsNull())
                return null;

            var sb = new StringBuilder();

            foreach (var c in text)
            {
                if (filter(c))
                    sb.Append(c);
            }

            return sb.ToString();
        }

        public static string KeepOnly(this string text, char characterToKeep)
        {
            return text.KeepOnly(c => c == characterToKeep);
        }

        public static string KeepOnly(this string text, char[] charactersToKeep)
        {
            return text.KeepOnly(c => charactersToKeep.Contains(c));
        }

        public static string KeepOnlyDigits(this string text)
        {
            return text.KeepOnly(c => c.IsDigit());
        }

        public static string KeepOnlyDigitsAnd(this string text, char additionalCharacterToKeep)
        {
            return text.KeepOnly(c => (char.IsDigit(c) || c == additionalCharacterToKeep));
        }

        public static string KeepOnlyDigitsAnd(this string text, char[] additionalCharactersToKeep)
        {
            return text.KeepOnly(c => (char.IsDigit(c) || additionalCharactersToKeep.Contains(c)));
        }

        public static string KeepOnlyLetters(this string text)
        {
            return text.KeepOnly(c => char.IsLetter(c));
        }

        public static string KeepOnlyLettersAnd(this string text, char additionalCharacterToKeep)
        {
            return text.KeepOnly(c => (char.IsLetter(c) || c == additionalCharacterToKeep));
        }

        public static string KeepOnlyLettersAnd(this string text, char[] additionalCharactersToKeep)
        {
            return text.KeepOnly(c => (char.IsLetter(c) || additionalCharactersToKeep.Contains(c)));
        }

        public static string KeepOnlyLettersAndDigits(this string text)
        {
            return text.KeepOnly(c => char.IsLetterOrDigit(c));
        }

        public static string KeepOnlyLettersAndDigitsAnd(this string text, char additionalCharacterToKeep)
        {
            return text.KeepOnly(c => (char.IsLetterOrDigit(c) || c == additionalCharacterToKeep));
        }

        public static string KeepOnlyLettersAndDigitsAnd(this string text, char[] additionalCharactersToKeep)
        {
            return text.KeepOnly(c => (char.IsLetterOrDigit(c) || additionalCharactersToKeep.Contains(c)));
        }

        public static string KeepOnlySpaces(this string text)
        {
            return text.KeepOnly(c => (c == ' '));
        }

        public static string KeepOnlyWhitespace(this string text)
        {
            return text.KeepOnly(c => (c.IsWhitespaceCharacter()));
        }
    }
}


0 Response to "string.KeepOnly"

Post a Comment