C# 如何使用LINQ按元音处理字符串列表?
我想在.NET LINQ中实现以下算法(C#首选):C# 如何使用LINQ按元音处理字符串列表?,c#,linq,functional-programming,C#,Linq,Functional Programming,我想在.NET LINQ中实现以下算法(C#首选): 输入是任意字符串。字符串的第一个字符保证是元音。例如,“alkjihgefdcb” 将字符串分成由元音分隔的块。例如,“alkj”,“ihg”,“efdcb” 按字母顺序对每个块进行排序。例如,“ajkl”,“ghi”,“bcdef” 将块重新连接在一起以生成输出字符串。例如,“ajklghibcdef” 是否有一种优雅(即纯功能性)的方法来实现这一点?第3步和第4步很简单,但第2步让我感到困惑,这似乎需要一些与SelectMany相反的东西
“alkjihgefdcb”
“alkj”
,“ihg”
,“efdcb”
“ajkl”
,“ghi”
,“bcdef”
“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和:
使用纯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
方法的副作用进行更新。当然
Regex.Split(input, @"(?=[aeiou])").Where(s => !string.IsNullOrWhiteSpace(s))
.OrderBy(n => n).Aggregate((a, b) => a + b);
如果您不想使用正则表达式,我们需要一个扩展方法:
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;
}
当然
如果您不想使用正则表达式,我们需要一个扩展方法:
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;
}
下面是一个使用LINQ(纯函数方法)的线性解决方案。这个想法是用
替换所有元音,然后在
上拆分
下面是一个使用LINQ(纯函数方法)的线性解决方案。这个想法是用
替换所有元音,然后在
上拆分
出于兴趣,为什么要跳过(1)?因为正则表达式是空的,这是因为在vowel@newStackExchangeInstance它总是以元音开头,所以第一个字符串是空的。我想这是没有必要的,因为它会在最后的连接中掉出来。只是出于兴趣,为什么要跳过(1)?因为正则表达式在一个连接上提前匹配,所以它是空的vowel@newStackExchangeInstance它总是以元音开头,所以第一个字符串是空的。我想这是没有必要的,因为它会在最后的连接中脱落。你介意一个额外的扩展方法吗?如果不是,请查看我的答案。您打算如何处理
y
可以根据上下文有条件地成为元音这一事实?假装它一直是,如果从来不是,就假装它,或者试着根据一个非单词的上下文来判断?你介意一个额外的扩展方法吗?如果不是,请查看我的答案。您打算如何处理y
可以根据上下文有条件地成为元音这一事实?假装它一直都是,如果从来都不是,就假装,或者试着根据一个非单词的上下文来判断?对不起!.Replace(“o”,“u”)行应为.Replace(“o”,“o”)这是一个输入错误。Aggregate
可以被调用string.Concat
来替换,这将从根本上提高效率。Aggregate
将创建大量不需要的中间字符串,并花费大量时间在它们之间复制相同的字符。抱歉!行.Replace(“o”,“u”)应该是.Replace(“o”,“o”,“o”)这是一个输入错误。聚合
可以被调用string.Concat
来代替,这将从根本上提高效率。聚合将创建大量不需要的中间字符串,并花费大量时间在它们之间复制相同的字符。
input.SplitOn('a', 'b', 'c', 'd', 'e').Select(s => new string(s.ToArray()))
.OrderBy(n => n).Aggregate((a, b) => a + b);
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);