学用 ASP.Net 之 "字符串" (4): string 类的扩展方法
string 类的扩展方法列表(基本相同于 IEnumerable<T> 接口的成员列表):
Aggregate<> //累加 All<> //是否都满足条件 Any<> //是否有一个满足条件 AsEnumerable<> // AsParallel<> // AsQueryable<> // Average<> //平均值 Cast<> // Concat<> //连接 Contains<> //是否包含 Count<> //总数 DefaultIfEmpty<> //指定默认空值 Distinct<> //去除重复 ElementAt<> //获取指定位置的元素 ElementAtOrDefault<> //同 ElementAt, 但获取失败则返回默认的空值 Except<> //差集 First<> //获取第一个元素 FirstOrDefault<> //同 First, 但获取失败返回默认的空值 GroupBy<> //分组 GroupJoin<> //关联分组 Intersect<> //交集 Join<> //串联 Last<> //获取最后一个元素 LastOrDefault<> //同 Last, 但获取失败返回默认的空值 LongCount<> //同 Count, 但返回 Int64 Max<> //最大值 Min<> //最小值 OfType<> // OrderBy<> //排序 OrderByDescending<> //倒排序 Reverse<> //翻转 Select<> //映射 SelectMany<> //深度映射 SequenceEqual<> // Single<> //获取只是唯一的元素, 不唯一或获取不到则异常 SingleOrDefault<> //获取只是唯一的元素, 不唯一则异常, 获取不到则取默认空值 Skip<> //获取指定序号之后的 SkipWhile<> //获取指定条件之后的 Sum<> //求和 Take<> //获取指定序号之前的 TakeWhile<> //获取指定条件之前的 ToArray<> // ToCharArray<> // ToDictionary<> // ToList<> // ToLookup<> // Union<> //并集 Where<> //筛选 Zip<> //合并
获取首尾的字符(First、Last、FirstOrDefault、LastOrDefault):
/* 函数及重载 */ First <Char>() // 函数名: First; <Char> 中的 Char 是返回值类型; () 表示这是一个无参数的重载 First <Char> (Func <Char, Boolean>) // 这里的参数是个函数, 其(函参)返回值是 Boolean 类型, 参数是 Char 类型. // <> 中是函数参数与返回值的列表, 最后一个是返回值. FirstOrDefault <Char>() // 同 First, 但如果找不到则返回默认值 null FirstOrDefault <Char> (Func <Char, Boolean>) // Last <Char>() // 顾名思义, 同上 Last <Char> (Func <Char, Boolean>) // LastOrDefault <Char>() // LastOrDefault <Char> (Func <Char, Boolean>) // //下面例子很容易理解: protected void Button1_Click(object sender, EventArgs e) { string str = "ABCDEFG"; char c1 = str.First(); // A char c2 = str.Last(); // G TextBox1.Text = string.Concat(c1, "\n", c2); } //下面例子使用了其第二种重载, 其参数是个函数, 使用了 Lambda 匿名函数表达式: protected void Button2_Click(object sender, EventArgs e) { string str = "ABCDEFG"; char c1 = str.First(p => p != 'A'); // B : 这是获取不是 A 的第一个字符 char c2 = str.Last(p => p < 70); // E : 这是获取字符编码值大于 70(F) 的倒数第一个字符 TextBox1.Text = string.Concat(c1, "\n", c2); } // Lambda 表达式中, // => 前面的是参数列表, 其类型可被自动识别所以可省略, 只有一个参数时可省略括号; 其中的 p 是自定义的变量名. // => 后面的是函数内容, 通常只有一句话; 但其必须返回指定的类型(本例中是 Boolean). //测试用于其它数组: protected void Button3_Click(object sender, EventArgs e) { int[] nArr = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; string[] sArr = { "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" }; int n1 = nArr.First(); //1 int n2 = nArr.First(x => x % 2 == 0); //2 string s1 = sArr.Last(); //ten string s2 = sArr.Last(s => s.Length == 5); //eight TextBox1.Text = string.Concat(n1, "\n", n2, "\n", s1, "\n", s2); }
获取指定位置的元素(ElementAt、ElementAtOrDefault):
protected void Button1_Click(object sender, EventArgs e) { string str = "Asp.Net 4.0"; char c1 = str.ElementAt(1); //s char c2 = str.ElementAtOrDefault(1); //s char c3 = str.ElementAtOrDefault(999); // bool b1 = c3 == '\x00'; //True TextBox1.Text = string.Concat(c1, "\n", c2, "\n", c3, "\n", b1); }
统计操作(Aggregate、Count、LongCount、Max、Min、Sum、Average):
//用数字数组测试比较合适 protected void Button1_Click(object sender, EventArgs e) { int[] nArr = { 2, 1, 4, 3, 6, 5 }; int n1 = nArr.Count(); //6 int n2 = nArr.Count(n => n % 2 == 0); //3 : 偶数元素总数 int n3 = nArr.Sum(); //21 int n4 = nArr.Max(); //6 int n5 = nArr.Min(); //1 double n6 = nArr.Average(); //3.5 int n7 = nArr.Aggregate((x, y) => x * y); //720 : 累乘 Int64 n8 = nArr.LongCount(); //6 : LongCount 和 Count 只是返回值的类型不同 string r = "\n"; TextBox1.Text = string.Concat(n1 + r + n2 + r + n3 + r + n4 + r + n5 + r + n6 + r + n7 + r + n8); } protected void Button2_Click(object sender, EventArgs e) { string str = "one two three four five six seven eight nine ten"; int n1 = str.Count(); //48 : 这相当于 str.Length int n2 = str.Count(s => s != ' '); //39 : 这是非空格字符的总数 char c1 = str.Max(); //x : 这是序号最大的字符 char c2 = str.Min(); //序号最小的字符在这里是空格 TextBox1.Text = string.Concat(n1, "\n", n2, "\n", c1, "\n", c2); } //通过 Aggregate 翻转字符串中的单词 protected void Button3_Click(object sender, EventArgs e) { string str = "one two three four five six seven eight nine ten"; string[] sArr = str.Split(' '); str = sArr.Aggregate((s1, s2) => s2 + " " + s1); //ten nine eight seven six five four three two one TextBox1.Text = str; }
集合操作(Intersect、Except、Union):
//测试整数数组的交集、差集、并集 protected void Button1_Click(object sender, EventArgs e) { int[] nArr1 = { 1, 2, 3, 4, 5, 6 }; int[] nArr2 = { 4, 5, 6, 7, 8, 9 }; IEnumerable<int> R1 = nArr1.Intersect(nArr2); // 返回类型可以写作隐式类型 var var R2 = nArr1.Except(nArr2); var R3 = nArr1.Union(nArr2); string s1 = string.Join("", R1); //456 string s2 = string.Join("", R2); //123 string s3 = string.Join("", R3); //123456789 TextBox1.Text = string.Concat(s1, "\n", s2, "\n", s3); } //测试字符串(字符数组)的交集、差集、并集 protected void Button2_Click(object sender, EventArgs e) { string str1 = "Asp.Net 3.5"; string str2 = "ASP.NET 4.0"; var R1 = str1.Intersect(str2); var R2 = str1.Except(str2); IEnumerable<char> R3 = str1.Union(str2); string s1 = string.Join("", R1); //A.N string s2 = string.Join("", R2); //spet35 string s3 = string.Join("", R3); //Asp.Net 35SPET40 TextBox1.Text = string.Concat(s1, "\n", s2, "\n", s3); } //定义一个 Person 类, 其有 Name 和 Age 两个属性 public class Person { public string Name { get; set; } public int Age { get; set; } public Person(string name, int age) { Name = name; Age = age; } // 构造函数 } //自定义的对比类, 以比较是否是同一个人 public class PersonComparer : IEqualityComparer<Person> { public bool Equals(Person p1, Person p2) { return p1.Name == p2.Name && p1.Age == p2.Age; } public int GetHashCode(Person obj) { return 0; } } //获取两组人的交集、差集、并集 protected void Button3_Click(object sender, EventArgs e) { string s1, s2, s3; s1 = s2 = s3 = ""; Person[] PersonArr1 = { new Person("AA", 11), new Person("BB", 22), new Person("CC", 33) }; Person[] PersonArr2 = { new Person("CC", 33), new Person("DD", 44), new Person("AA", 55) }; var ps1 = PersonArr1.Intersect(PersonArr2, new PersonComparer()); var ps2 = PersonArr1.Except(PersonArr2, new PersonComparer()); IEnumerable<Person> ps3 = PersonArr1.Union(PersonArr2, new PersonComparer()); foreach (Person p in ps1) { s1 += string.Format("{0}:{1} ", p.Name, p.Age); } //CC:33 foreach (Person p in ps2) { s2 += string.Format("{0}:{1} ", p.Name, p.Age); } //AA:11 BB:22 foreach (Person p in ps3) { s3 += string.Format("{0}:{1} ", p.Name, p.Age); } //AA:11 BB:22 CC:33 DD:44 AA:55 TextBox1.Text = string.Concat(s1, "\n", s2, "\n", s3); }
连接、合并与串联(Concat、Zip、Join):
//Concat protected void Button1_Click(object sender, EventArgs e) { int[] nArr1 = { 1, 2, 3 }; int[] nArr2 = { 4, 5, 6 }; var R1 = nArr1.Concat(nArr2); var R2 = nArr2.Concat(nArr1); var R3 = nArr1.Concat(nArr1); string s1 = string.Join("", R1); //123456 string s2 = string.Join("", R2); //456123 string s3 = string.Join("", R3); //123123 TextBox1.Text = string.Format("{0}\n{1}\n{2}", s1, s2, s3); } //Zip protected void Button2_Click(object sender, EventArgs e) { string[] sArr = { "one", "two", "there" }; int[] nArr = { 1, 2, 3 }; var R1 = sArr.Zip(nArr, (x1, x2) => x1 + ":" + x2 + " "); var R2 = sArr.Zip(nArr, (x1, x2) => x2 + ":" + x1 + " "); string s1 = string.Join("", R1); //one:1 two:2 there:3 string s2 = string.Join("", R2); //1:one 2:two 3:there TextBox1.Text = string.Concat(s1, "\n", s2); } //Join protected void Button3_Click(object sender, EventArgs e) { int[] nArr = { 1, 2, 3, 4, 5, 6, 7 }; string[] sArr = { "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" }; var R = nArr.Join(sArr, n => n, s => s.Length, (n, s) => new { n, s }); string str = ""; foreach (var obj in R) { str += obj.n + " : " + obj.s + "\n"; } TextBox1.Text = str; /* 输出结果: 3 : one 3 : two 3 : six 3 : ten 4 : four 4 : five 4 : nine 5 : three 5 : seven 5 : eight */ }
去除重复(Distinct):
protected void Button1_Click(object sender, EventArgs e) { string str = "aabbccc"; var cs = str.Distinct(); foreach (char c in cs) { TextBox1.Text += c; } //abc } protected void Button2_Click(object sender, EventArgs e) { int[] nArr = { 1, 3, 2, 4, 3, 5, 4, 6, 5, 7, 6, 8, 7, 9, 8, 0 }; var ns = nArr.Distinct().OrderBy(x => -x); foreach (int n in ns) { TextBox1.Text += n.ToString(); } //9876543210 }
排序(OrderBy、OrderByDescending):
protected void Button1_Click(object sender, EventArgs e) { int[] nArr = { 1, 3, 2, 4, 3, 5 }; string[] sArr = { "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" }; string str = "Asp.Net"; var R1 = nArr.OrderBy(x => x); var R2 = nArr.OrderByDescending(x => x); var R3 = sArr.OrderBy(x => x); var R4 = sArr.OrderByDescending(x => x); var R5 = str.OrderBy(x => x.ToString().ToLower()); var R6 = str.OrderByDescending(x => x.ToString().ToLower()); string s1 = string.Join("", R1); //123345 string s2 = string.Join("", R2); //543321 string s3 = string.Join(" ", R3); //eight five four nine one seven six ten three two string s4 = string.Join(" ", R4); //two three ten six seven one nine four five eight string s5 = string.Join("", R5); //.AeNpst string s6 = string.Join("", R6); //tspNeA. TextBox1.Text = string.Concat(s1, "\n", s2, "\n", s3, "\n", s4, "\n", s5, "\n", s6); }
翻转(Reverse):
protected void Button1_Click(object sender, EventArgs e) { string str = "Asp.Net"; var cs = str.Reverse(); foreach (char c in cs) { TextBox1.Text += c; } //teN.psA }
筛选(Where):
protected void Button1_Click(object sender, EventArgs e) { int[] nArr = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; string[] sArr = { "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" }; var R1 = nArr.Where(n => n % 2 == 0); var R2 = sArr.Where(s => s.Length == 3); string s1 = string.Join(", ", R1); //2, 4, 6, 8 string s2 = string.Join(", ", R2); //one, two, six, ten TextBox1.Text = string.Concat(s1, "\n", s2); }
映射(Select、SelectMany):
//Select protected void Button1_Click(object sender, EventArgs e) { int[] nArr = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; string[] sArr = { "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" }; var R1 = nArr.Select(n => n * n); var R2 = sArr.Select((str, index) => (index+1) + ":" + str.ToUpper()); string s1 = string.Join(",", R1); //1,4,9,16,25,36,49,64,81 string s2 = string.Join(" ", R2); //1:ONE 2:TWO 3:THREE 4:FOUR 5:FIVE 6:SIX 7:SEVEN 8:EIGHT 9:NINE 10:TEN TextBox1.Text = string.Concat(s1, "\n", s2); } //Select 与 SelectMany protected void Button2_Click(object sender, EventArgs e) { string[] sArr = { "AA:BB:CC", "DD:EE:FF", "GG:HH:II" }; var R1 = sArr.Select(arr => arr.Split(':')); var R2 = sArr.SelectMany(arr => arr.Split(':')); var s1 = string.Join(" ", R1); //System.String[] System.String[] System.String[] var s2 = string.Join(" ", R2); //AA BB CC DD EE FF GG HH II var s3 = ""; foreach (string[] ss in R1) { s3 += string.Join(" ", ss) + "; "; } //AA BB CC; DD EE FF; GG HH II; TextBox1.Text = string.Concat(s1, "\n", s2 + "\n" + s3); }
分组(GroupBy、GroupJoin):
public class Person { public string Name { get; set; } public int Age { get; set; } } protected void Button1_Click(object sender, EventArgs e) { Person[] pArr = { new Person { Name="AA", Age=11 }, new Person { Name="BB", Age=22 }, new Person { Name="CC", Age=33 }, new Person { Name="DD", Age=11 }, new Person { Name="EE", Age=22 }, new Person { Name="FF", Age=33 }, new Person { Name="GG", Age=11 } }; var R1 = pArr.GroupBy(p => p.Age, p => p.Name); var R2 = pArr.GroupBy(p => p.Age, p => p); string str1 = ""; foreach (IGrouping<int, string> group in R1) { str1 += group.Key + "\n"; foreach (string n in group) { str1 += "\t" + n + "\n"; } } string str2 = ""; foreach (IGrouping<int, Person> group in R2) { str2 += group.Key + "\n"; foreach (Person p in group) { str2 += string.Format("\t{0}:{1}\n", p.Name, p.Age); } } TextBox1.Text = string.Format("{0}----------\n{1}", str1, str2); /* 输出结果: 11 AA DD GG 22 BB EE 33 CC FF ---------- 11 AA:11 DD:11 GG:11 22 BB:22 EE:22 33 CC:33 FF:33 */ } //使用 GroupJoin, 测试效果同上 protected void Button1_Click(object sender, EventArgs e) { int[] nArr = { 11, 22, 33 }; Person[] pArr = { new Person { Name="AA", Age=11 }, new Person { Name="BB", Age=22 }, new Person { Name="CC", Age=33 }, new Person { Name="DD", Age=11 }, new Person { Name="EE", Age=22 }, new Person { Name="FF", Age=33 }, new Person { Name="GG", Age=11 } }; var R1 = nArr.GroupJoin(pArr, n => n, p => p.Age, (n, ps) => new { MyKey = n, MyNames = ps.Select(p => p.Name) }); var R2 = nArr.GroupJoin(pArr, n => n, p => p.Age, (n, ps) => new { MyKey = n, MyNames = ps }); string str1 = ""; foreach (var obj in R1) { str1 += obj.MyKey + "\n"; foreach (string s in obj.MyNames) { str1 += string.Format("\t{0}\n", s); } } string str2 = ""; foreach (var obj in R2) { str2 += obj.MyKey + "\n"; foreach (var p in obj.MyNames) { str2 += string.Format("\t{0}:{1}\n", p.Name, p.Age); } } TextBox1.Text = string.Format("{0}----------\n{1}", str1, str2); }
获取指定条件之后的(Skip、SkipWhile)或之前的(Take、TakeWhile):
//Skip、SkipWhile protected void Button1_Click(object sender, EventArgs e) { int[] nArr = { 1, 3, 2, 4, 3, 5 }; var R1 = nArr.Skip(3); //取第 3 个元素之后的 var R2 = nArr.OrderBy(n => n).Skip(3); //先排序, 再取第 3 个元素之后的 var R3 = nArr.OrderByDescending(n => n).Skip(3); //先倒排序, 再取第 3 个元素之后的 var R4 = nArr.OrderBy(n => n).SkipWhile(n => n <= 3); //先排序(123345), 从不满足条件开始, 之后的 var R5 = nArr.SkipWhile((num, index) => num != index); // 从第二个元素开始, 数字和序号就不一样了 string s1 = string.Join("", R1); //435 string s2 = string.Join("", R2); //345 string s3 = string.Join("", R3); //321 string s4 = string.Join("", R4); //45 string s5 = string.Join("", R5); //2435 TextBox1.Text = string.Format("{0}\n{1}\n{2}\n{3}\n{4}", s1, s2, s3, s4, s5); } //Take、TakeWhile 用法同上, 只是获取之前的 protected void Button2_Click(object sender, EventArgs e) { int[] nArr = { 1, 3, 2, 4, 3, 5 }; var R1 = nArr.Take(3); var R2 = nArr.OrderBy(n => n).Take(3); var R3 = nArr.OrderByDescending(n => n).Take(3); var R4 = nArr.OrderBy(n => n).TakeWhile(n => n <= 3); var R5 = nArr.TakeWhile((num, index) => num != index); string s1 = string.Join("", R1); //132 string s2 = string.Join("", R2); //123 string s3 = string.Join("", R3); //543 string s4 = string.Join("", R4); //1233 string s5 = string.Join("", R5); //13 TextBox1.Text = string.Format("{0}\n{1}\n{2}\n{3}\n{4}", s1, s2, s3, s4, s5); }
All 与 Any:
//都满足条件时 All 才返回 True protected void Button1_Click(object sender, EventArgs e) { int[] nArr = { 1, 3, 5, 7, 9 }; bool b1 = nArr.All(n => n % 2 == 0); //False bool b2 = nArr.All(n => n % 2 == 1); //True TextBox1.Text = string.Concat(b1, "\n", b2); } //其中一个满足条件 Any 就返回 True protected void Button2_Click(object sender, EventArgs e) { string str1 = "Delphi"; string str2 = "Asp.Net"; string str3 = ""; bool b1 = str1.Any(); //True bool b2 = str2.Any(); //True bool b3 = str3.Any(); //False bool b4 = str1.Any(c => c == 'D'); //True bool b5 = str2.Any(c => c == 'D'); //False bool b6 = str2.Any(c => c == 'D'); //False TextBox1.Text = string.Concat(b1, "\n", b2, "\n", b3, "\n", b4, "\n", b5, "\n", b6); }
是否包含(Contains):
protected void Button1_Click(object sender, EventArgs e) { string str = "Asp.Net 4.0"; bool b1 = str.Contains('4'); //True bool b2 = str.Contains("Net 4.0"); //True bool b3 = str.Contains("Net4.0"); //False TextBox1.Text = string.Concat(b1, "\n", b2, "\n", b3, "\n"); }
获取只是唯一的元素(Single、SingleOrDefault):
protected void Button1_Click(object sender, EventArgs e) { string str = "Microsoft"; char c1, c2, c3, c4, c5, c6; c1 = c2 = c3 = c4 = c5 = c6 = '*'; //Single c1 = str.Single(c => c == 'M'); //M try { c2 = str.Single(c => c == 'o'); } catch (Exception err) { Response.Write(err.Message + "<br/>"); } // 序列包含一个以上的匹配元素 try { c3 = str.Single(c => c == 'A'); } catch (Exception err) { Response.Write(err.Message + "<br/>"); } // 序列不包含任何匹配元素 //SingleOrDefault c4 = str.SingleOrDefault(c => c == 'M'); //M try { c5 = str.SingleOrDefault(c => c == 'o'); } catch (Exception err) { Response.Write(err.Message + "<br/>"); } // 序列包含一个以上的匹配元素 c6 = str.SingleOrDefault(c => c == 'A'); // 这不会激发异常 TextBox1.Text = string.Format("{0}{1}{2}{3}{4}{5}", c1, c2, c3, c4, c5, c6); //M**M* }
指定默认空值(DefaultIfEmpty):
protected void Button1_Click(object sender, EventArgs e) { string str1 = "Asp.Net 3.5"; string str2 = ""; string r1 = string.Join("|", str1.DefaultIfEmpty()); //A|s|p|.|N|e|t| |3|.|5 string r2 = string.Join("|", str2.DefaultIfEmpty()); // string r3 = string.Join("|", str2.DefaultIfEmpty('*')); //* TextBox1.Text = string.Concat(r1, "\n", r2, "\n", r3); }