From 00a1941b403e25f6cf8f902cb5d80c9cfe60ba2f Mon Sep 17 00:00:00 2001 From: Elivo Date: Wed, 29 Oct 2025 16:57:25 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=20TextUtility.Distinct=20?= =?UTF-8?q?=E5=8F=82=E6=95=B0=EF=BC=8C=E5=9C=A8=E5=8C=B9=E9=85=8D=E6=97=B6?= =?UTF-8?q?=E4=BC=98=E5=85=88=E4=BA=8E=20Linq=EF=BC=8C=E5=B9=B6=E6=8F=90?= =?UTF-8?q?=E4=BE=9B=E6=89=A9=E5=B1=95=E6=96=B9=E6=B3=95=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Apewer/TextUtility.cs | 162 +++++++++++++++++++++++++++--------------- 1 file changed, 104 insertions(+), 58 deletions(-) diff --git a/Apewer/TextUtility.cs b/Apewer/TextUtility.cs index 5dd5fca..d5928b0 100644 --- a/Apewer/TextUtility.cs +++ b/Apewer/TextUtility.cs @@ -2,7 +2,6 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Runtime.InteropServices; using System.Text; using System.Text.RegularExpressions; @@ -13,17 +12,27 @@ namespace Apewer public static class TextUtility { + const string LetterChars = LowerCase + UpperCase; const string BlankChars = "  \n\r\t\f\b\a"; // 在 IsBlank 和 Trim 中视为空白的字符。 const string LineFeed = "\r\n"; // 换行符,由 ASCII 13 和 ASCII 10 组成。 - const string SpaceDbc = " "; - const string SpaceSbc = " "; - const string LucidChars = "3456789acefhknpstwxyz"; - const string KeyChars = "0123456789abcdefghijklmnopqrstuvwxyz"; - const string HexChars = "0123456789abcdef"; - const string NumericChars = "0123456789"; - const string LowerChars = "abcdefghijklmnopqrstuvwxyz"; - const string UpperChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - const string LetterChars = LowerChars + UpperChars; + + /// 半角空格。 + public const string Space = " "; + + /// 全角空格。 + public const string SpaceSbc = " "; + + /// 十进制字符。 + public const string Decimal = "0123456789"; + + /// 十六进制字符。 + public const string Hexadecimal = "0123456789abcdef"; + + /// 小写字母。 + public const string LowerCase = "abcdefghijklmnopqrstuvwxyz"; + + /// 大写字母。 + public const string UpperCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; /// UTF-8 BOM。 public static byte[] Bom { get => new byte[] { 0xEF, 0xBB, 0xBF }; } @@ -31,8 +40,11 @@ namespace Apewer /// CRLF。 public const string CRLF = "\r\n"; + /// CR。 + public const char CR = '\r'; + /// LF。 - public const string LF = "\n"; + public const char LF = '\n'; /// 长度为 0 的空字符串。 public const string Empty = ""; @@ -220,9 +232,6 @@ namespace Apewer return new string(output); } - /// 获取指定长的的空格。 - public static string Space(int length) => Duplicate(' ', length); - /// 将文本以转换为字节数组。默认 Encoding 为 UTF-8。 public static byte[] Bytes(string text, Encoding encoding = null) { @@ -650,70 +659,107 @@ namespace Apewer public static string Random(int length, string pool = "0123456789abcdefghijklmnopqrstuvwxyz") { if (length < 1) return Empty; - if (IsEmpty(pool)) return Duplicate(SpaceDbc, length); + if (IsEmpty(pool)) return Duplicate(Space, length); var array = new char[length]; var max = pool.Length - 1; for (var i = 0; i < length; i++) array[i] = pool[NumberUtility.Random(0, max)]; return new string(array); } - /// 对字符串列表去重。指定 valid 参数时将去除无效字符串。 - /// - /// - public static string[] Distinct(IEnumerable strings, bool valid = false) + /// 对字符串集合去重,同时去除 NULL 值和空字符串。 + public static string[] Distinct(this IEnumerable strings) => Distinct(strings, false, false); + + /// 对字符串集合去重。 + /// 字符串集合。 + /// 保留空字符串。 + /// 保留 NULL 值。 + public static string[] Distinct(this IEnumerable strings, bool withEmpty, bool withNull) { if (strings == null) return new string[0]; - const string space = " "; - var hasNull = false; - var hasEmpty = false; - var hasSpace = false; + // 保留 NULL 和空字符串 + var @null = false; + var empty = false; - var array = new ArrayBuilder(); - foreach (var s in strings) + // 遍历,重组 + var cache = new List(); + if (strings is IList list) { - if (s == null) - { - if (valid) continue; - if (hasNull) continue; - hasNull = true; - array.Add(s); - continue; - } - if (s == Empty) + var count = list.Count; + cache.Capacity = count; + for (var i = 0; i < count; i++) { - if (valid) continue; - if (hasEmpty) continue; - hasEmpty = true; - array.Add(s); - continue; + var item = list[i]; + + if (item == null) + { + if (withNull && !@null) + { + cache.Add(item); + @null = true; + } + continue; + } + if (item == Empty) + { + if (withEmpty && !empty) + { + cache.Add(item); + empty = true; + } + continue; + } + + var added = false; + for (var j = 0; j < cache.Count; j++) + { + if (cache[j] == item) + { + added = true; + break; + } + } + if (!added) cache.Add(item); } - if (s == space) + } + else + { + foreach (var item in strings) { - if (valid) continue; - if (hasSpace) continue; - hasSpace = true; - array.Add(s); - continue; - } + if (item == null) + { + if (withNull && !@null) + { + cache.Add(item); + @null = true; + } + continue; + } + if (item == Empty) + { + if (withEmpty && !empty) + { + cache.Add(item); + empty = true; + } + continue; + } - var exist = false; - for (var i = 0; i < array.Length; i++) - { - if (array[i] == s) + var added = false; + for (var j = 0; j < cache.Count; j++) { - exist = true; - break; + if (cache[j] == item) + { + added = true; + break; + } } + if (!added) cache.Add(item); } - if (exist) continue; - - array.Add(s); } - return array.Export(); + return cache.ToArray(); } - /// 约束字符串中的字符,只包含指定的字符。 public static string Restrict(string text, char[] chars) { @@ -748,7 +794,7 @@ namespace Apewer public static string RestrictLetters(string text) => Restrict(text, LetterChars.ToCharArray()); /// 约束字符串中的字符,只包含数字。 - public static string RestrictNumeric(string text) => Restrict(text, NumericChars.ToCharArray()); + public static string RestrictNumeric(string text) => Restrict(text, Decimal.ToCharArray()); /// 返回此字符串的安全键副本,只保留数据记录主键中可能出现的字符,默认限制长度为 255 字符。 public static string SafeKey(string text, int maxLength = 255)