如何使用LINQ按元音处理字符串列表
本文关键字:处理 字符串 列表 何使用 LINQ | 更新日期: 2023-09-27 18:20:34
我想在.NET LINQ(C#首选)中实现以下算法:
-
输入是任意字符串。字符串的第一个字符保证是元音。例如
"alkjihgefdcb"
-
将字符串分成由元音分隔的块。例如
"alkj"
、"ihg"
、"efdcb"
-
按字母顺序对每个区块进行排序。例如
"ajkl"
、"ghi"
、"bcdef"
-
将块重新连接在一起以生成输出字符串。例如
"ajklghibcdef"
有没有一种优雅的(即纯粹功能性的)方法可以做到这一点?第3步和第4步很简单,但我在第2步上遇到了麻烦,这似乎需要与SelectMany相反的东西。谢谢
编辑:我很欣赏Regex解决方案,但我正在寻找一种纯粹基于LINQ的方法。在我的实际应用程序中,字符串是域对象的列表,因此Regex不容易适用。
当然。
Regex.Split(input, @"(?=[aeiou])").Where(s => !string.IsNullOrWhiteSpace(s))
.OrderBy(n => n).Aggregate((a, b) => a + b);
如果你不想使用Regex,我们需要一个扩展方法:
public static IEnumerable<IEnumerable<T>> SplitOn<T>(this IEnumerable<T> source, params T[] splitObjs)
{
//appropriate error checking, check for null etc
if (!source.Any() || !splitObjs.Any()) return new[]{source};
List<T> buffer = new List<T>()
foreach (T item in source)
{
if (splitObjs.Contains(item) && buffer.Any())
{
yield return buffer;
buffer.Clear();
}
buffer.Add(item);
}
if (buffer.Any()) yield return buffer;
}
然后它应该简单到:
input.SplitOn('a', 'b', 'c', 'd', 'e').Select(s => new string(s.ToArray()))
.OrderBy(n => n).Aggregate((a, b) => a + b);
您可以使用Linq和正则表达式:
string.Join(
string.Empty,
Regex.Matches("alkjihgefdcb", "[aeiou][^aeiou]+")
.Cast<Match>()
.Select(m => string.Join(string.Empty, m.Value.OrderBy(c => c))));
// ajklghibcdef
或者更好:
string.Join(
string.Empty,
Regex.Split("alkjihgefdcb", "(?=[aeiou])")
.Select(m => string.Join(string.Empty, m.OrderBy(c => c))));
// ajklghibcdef
使用纯Linq:
var i = 0;
string.Join(
string.Empty,
"alkjihgefdcb".GroupBy(c => "aeiou".IndexOf(c) == -1 ? i : ++i)
.SelectMany(g => g.OrderBy(c => c)));
// ajklghibcdef
尽管我不太愿意称之为真正的函数,因为它依赖于i
通过GroupBy
方法的副作用进行更新。
这里有一个使用LINQ(纯函数方式)的线性解决方案。这个想法是用#
替换所有元音,然后在#
上拆分
string input = "alkjihgefdcb";
input = input
.Replace("a","#a")
.Replace("e","#e")
.Replace("i","#i")
.Replace("o","#u")
.Replace("u","#u")
.Split(new char[]{'#'},StringSplitOptions.RemoveEmptyEntries)
.Select (i => new string(i.ToCharArray().OrderBy (x => x).ToArray()))
.Aggregate ((a,b) => a + b);