C# StringHelpers / String helpers

Date: 2019-11-11
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace Default
{
    public class StringHelpers
    {
        // generics
        public static IEnumerable<IEnumerable<T>> Split<T>(IEnumerable<T> src, int size) 
                    => src.Where((x, i) => i % size == 0).Select((x, i) => src.Skip(i * size).Take(size));

        public static IEnumerable<T> Select<T>(params T[] args) => args;
        public static List<T> List<T>(params T[] args) => args.ToList();


        // string specific
        public static string BuildLines(params string[] lines) => string.Join(Environment.NewLine, lines.Where(x => !string.IsNullOrWhiteSpace(x)).Select(x => x.Trim()));
        
        public static bool StrEquals(string a, string b) => string.Equals((a ?? "").Trim(), (b ?? "").Trim(), StringComparison.OrdinalIgnoreCase);

        public static string FirstNonEmpty(params string[] args) => args.FirstOrDefault(x => !string.IsNullOrWhiteSpace(x));

        public static bool AnyEmpty(params string[] args) => args.Any(x => string.IsNullOrWhiteSpace(x));

        public static string LimitString(string str, int length) => str?.Substring(0, Math.Min(str.Length, length));

        public static IEnumerable<string> SplitSizes(string str, params int[] sizes)
        {
            var start = 0;
            return sizes.Select(s => {
                if (start + s > str.Length) return "";
                var result = str.Substring(start, s);
                start += s;
                return result;
            });
        }    

        public static string JoinUrl(string baseUrl, params string[] parts)
        {
            var partList = new List<string>();
            partList.Add(baseUrl.TrimEnd('/'));
            foreach (string part in parts)
            {
                if (!String.IsNullOrEmpty(part)) partList.Add(part);
            }
            return String.Join("/", partList);
        }

        private static readonly Regex nonAsciiRegex = new Regex("[^ -~]+", RegexOptions.Compiled);
        public static string ReplaceNonAsciiChars(string input)
        {
            if (string.IsNullOrWhiteSpace(input))
                return input;
            return nonAsciiRegex.Replace(input, "");
        }

		public static string ShortenText(string caption, int length)
		{
			if (string.IsNullOrEmpty(caption) || length <= 0)
				return "";

            if (caption.Length <= length)
                return caption;
            
            int count = length - 5;
            int lastIndex = caption.LastIndexOfAny(new char[] { ' ', ',', '.', '-' }, length - 1, count);
            if (lastIndex >= 0)
                return caption.Remove(lastIndex) + " ...";
            else
                return caption.Remove(length - 4) + " ...";
        }

		public static string ShortenTextSimple(string caption, int length)
		{
			if (string.IsNullOrEmpty(caption) || length <= 0)
				return "";
            if (caption.Length <= length)
                return caption;

            return caption.Remove(length - 3) + "...";
        }

        public static List<string> SplitString(string str, int chunkSize)
        {
            if (string.IsNullOrWhiteSpace(str))
                str = "";

            var chunks = new List<string>(); ;
            int stringLength = str.Length;
            for (int i = 0; i < stringLength; i += chunkSize)
            {
                if (i + chunkSize > stringLength) chunkSize = stringLength - i;
                chunks.Add(str.Substring(i, chunkSize));
            }
            if (chunks.Count == 0)
                chunks.Add("");

            return chunks;
        }

        public static string Right(string value, int length) => value.Substring(value.Length - length);

        public static string UppercaseFirst(string str)
        {
            if (string.IsNullOrEmpty(str)) 
                return str;
            return char.ToUpper(str[0]) + str.Substring(1);
        }

        public static bool ContainsIc(string src, string item) => HasString(src, item);

		public static bool HasString(string src, string item)
		{
			return src?.IndexOf(item ?? "", StringComparison.OrdinalIgnoreCase) >= 0;
		}

        public static string Repeat(string s, int count) => new StringBuilder(s.Length * count).Insert(0, s, count).ToString();
		
        private static readonly string[] trueValues = { "true", "1", "y", "yes" }; // add your language yes value here
        public static bool StringToBool(string val) => trueValues.Contains(val?.Trim(), StringComparer.OrdinalIgnoreCase);

        public static string StreamToString(Stream stream)
        {
            if (stream.CanSeek) stream.Position = 0;
            return new StreamReader(stream).ReadToEnd();
        }		
        
        public static string GetLastCharacters(string s, int count) => string.Concat($"{s}".Trim().TakeLast(count));
        
        public static bool AreFirstNCharsEqual(string a, string b, int n)
        {
            if (string.IsNullOrEmpty(a) && string.IsNullOrEmpty(b)) return false;
            if (a?.Length < n || b?.Length < n) return false;
            return string.Equals(a.Substring(0, n), b.Substring(0, n), StringComparison.OrdinalIgnoreCase);
        }
        
        public static string RemoveDiacritics(string text)
        {
            var normalizedString = text.Normalize(NormalizationForm.FormD);
            var stringBuilder = new StringBuilder();
            foreach (var c in normalizedString)
            {
                var unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c);
                if (unicodeCategory != UnicodeCategory.NonSpacingMark)
                {
                    stringBuilder.Append(c);
                }
            }
            return stringBuilder.ToString().Normalize(NormalizationForm.FormC);
        }
        
        private static readonly Regex LineRegex = new Regex(@"\r?\n|\r", RegexOptions.Compiled);

        public static string[] GetLines(string s) => LineRegex.Split(s);


        public static string RemoveEmptyLines(string text)
        {
            return Regex.Replace(text, @"^\s*$[\r\n]*", string.Empty, RegexOptions.Multiline);
        }
        
        private static readonly Regex MultiLineRegex = new Regex(@"^\s*$[\r\n]*", RegexOptions.Multiline | RegexOptions.Compiled);
        public static string RemoveEmptyLines(string text) => MultiLineRegex.Replace(text, string.Empty);
        public static string RemoveEmptyLinesWithSingle(string text) => MultiLineRegex.Replace(text, "\n");

        public static string AddDotsToFirstLineWhenMultiline(string v)
        {
            var lines = GetLines(v.Trim()).Where(x => !string.IsNullOrWhiteSpace(v)).ToList();
            if (lines.Count > 1)
                lines[0] = $"{lines[0]}...";
            return string.Join(Environment.NewLine, lines);
        }
        
        public static List<int> GetNumbersFromString(string input) => regexDigitGroups.Matches(input)?.Select(x => x.Value.TrimStart('0')).Select(int.Parse).ToList() ?? [];

        private static Regex regexDigitGroups = new(@"\d+", RegexOptions.Compiled);
    }
}
28350cookie-checkC# StringHelpers / String helpers