Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用LINQ按元音处理字符串列表?_C#_Linq_Functional Programming - Fatal编程技术网

C# 如何使用LINQ按元音处理字符串列表?

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相反的东西

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

  • 输入是任意字符串。字符串的第一个字符保证是元音。例如,
    “alkjihgefdcb”

  • 将字符串分成由元音分隔的块。例如,
    “alkj”
    “ihg”
    “efdcb”

  • 按字母顺序对每个块进行排序。例如,
    “ajkl”
    “ghi”
    “bcdef”

  • 将块重新连接在一起以生成输出字符串。例如,
    “ajklghibcdef”

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

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

    您可以使用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
    方法的副作用。

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