我知道String.Split的概念之前已经通过多种不同的方法得到了解决,但我对这个问题的LINQ解决方案特别感兴趣.
我试图编写一个扩展类来处理拆分,但两次尝试都有一些重大问题.所以对于以下内容:
string s = "ABCDEFGHIJKLMNOPQRSTUVWX";
var results = s.SplitEvery(4);
Run Code Online (Sandbox Code Playgroud)
我想要一个列表,如:{"ABCD","EFGH","IJKL","MNOP","QRST","UVWX"}
这是我的扩展类:
public static class Extensions
{
public static List<string> SplitEvery(this string s, int n)
{
List<string> list = new List<string>();
var Attempt1 = s.Select((c, i) => i % n== 0 ? s.Substring(i, n) : "|").Where(x => x != "|").ToList();
var Attempt2 = s.Where((c, i) => i % n== 0).Select((c, i) => s.Substring(i, n)).ToList();
return list;
}
}
Run Code Online (Sandbox Code Playgroud)
尝试1插入一个虚拟字符串"|" 每次不满足条件时,都会删除虚拟字符串的所有实例以创建最终列表.它有效,但创建坏字符串似乎是一个不必要的额外步骤.此外,如果字符串不能被n整除,则此尝试将失败.
尝试2是我试图仅选择索引可被N整除的子串,但Select语句中的'i'值与Where语句中的'i'值不对应,因此我得到如下结果:{" ABCD","BCDE"等...}
我觉得我接近一个好的解决方案,但可以在正确的方向上使用有用的推动.有什么建议?
[编辑]
我最后提出了一些处理我的字符串拆分器的建议.它可能不是最快的,但作为LINQ的新手,这个实现对我来说是最简洁易懂的.
public static List<string> SplitEvery(this string s, int size)
{
return s.Select((x, i) => i)
.Where(i => i % size == 0)
.Select(i => String.Concat(s.Skip(i).Take(size))).ToList();
}
Run Code Online (Sandbox Code Playgroud)
感谢所有优秀的建议.
I4V*_*I4V 25
string s = "ABCDEFGHIJKLMNOPQRSTUVWX";
var results = s.Select((c, i) => new { c, i })
.GroupBy(x => x.i / 4)
.Select(g => String.Join("",g.Select(y=>y.c)))
.ToList();
Run Code Online (Sandbox Code Playgroud)
您也可以使用morelinq的批次
var res = s.Batch(4).Select(x => String.Join("", x)).ToList();
Run Code Online (Sandbox Code Playgroud)
如果你不介意使用副作用,这也是可能的
var res2 = s.SplitEvery(4).ToList();
public static IEnumerable<string> SplitEvery(this string s, int n)
{
int index = 0;
return s.GroupBy(_=> index++/n).Select(g => new string(g.ToArray()));
}
Run Code Online (Sandbox Code Playgroud)
当然每个字符串操作问题都值得一个正则表达式的答案:)
var res3 = Regex.Split(s, @"(?<=\G.{4})");
Run Code Online (Sandbox Code Playgroud)
你可以使用这个扩展方法,它使用简单的子字符串获取(我相信它比枚举字符并将它们连接成字符串更快):
public static IEnumerable<string> SplitEvery(this string s, int length)
{
int index = 0;
while (index + length < s.Length)
{
yield return s.Substring(index, length);
index += length;
}
if (index < s.Length)
yield return s.Substring(index, s.Length - index);
}
Run Code Online (Sandbox Code Playgroud)
这是另一个解决方案:
var result = s.Select((x, i) => i)
.Where(i => i % 4 == 0)
.Select(i => s.Substring(i, s.Length - i >= 4 ? 4 : s.Length - i));
Run Code Online (Sandbox Code Playgroud)
public static IEnumerable<string> SplitEvery(this string s, int length)
{
return s.Where((c, index) => index % length == 0)
.Select((c, index) => String.Concat(
s.Skip(index * length).Take(length)
)
);
}
Run Code Online (Sandbox Code Playgroud)
陪审团对此是否new String(chars.ToArray())会更快或更慢有所了解String.Concat(chars).
您当然可以追加.ToList()一个List而不是IEnumerable.