0

我想在 .NET LINQ 中实现以下算法(首选 C#):

  1. 输入是任意字符串。保证字符串的第一个字符是元音。例如"alkjihgefdcb"

  2. 将字符串分成由元音分隔的块。例如"alkj", "ihg","efdcb"

  3. 按字母顺序对每个块进行排序。例如"ajkl", "ghi","bcdef"

  4. 将块重新连接在一起以生成输出字符串。例如"ajklghibcdef"

有没有一种优雅的(即纯粹的功能性)方法来做到这一点?第 3 步和第 4 步很简单,但我对第 2 步感到困惑,这似乎需要与 SelectMany 相反的东西。谢谢。

编辑:我很欣赏正则表达式解决方案,但我正在寻找一种纯粹基于 LINQ 的方法。在我的实际应用程序中,字符串是域对象的列表,因此 Regex 不容易适用。

4

3 回答 3

2

当然。

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);
于 2013-07-01T23:05:26.367 回答
1

您可以使用 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

于 2013-07-01T23:01:27.560 回答
0

这是一种使用 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);
于 2013-07-02T18:10:50.537 回答