通过兄弟分隔符元素对相邻元素进行分组

  • 本文关键字:元素 兄弟 分隔符 c# linq
  • 更新时间 :
  • 英文 :


在将"人类可读"的数据解析为更方便的数据结构时,我经常遇到的一个问题是:

假设我有一个兄弟元素列表:

var input = new[] {"moo", "*", "foo", "bar", "baz", "*", "roo", 
                   "moo", "*", "*", "hoot", "*", "boot"};

我知道*是一个分隔符,它将所有相邻元素分组,直到下一个分隔符。因此,与此输入相关联的"更方便"的数据结构是:

var expectedOutput = new List<List<string>>
  {
    new List<string> {"moo"},
    new List<string> {"*", "foo", "bar", "baz"},
    new List<string> {"*", "roo", "moo"},
    new List<string> {"*"},
    new List<string> {"*", "hoot"},
    new List<string> {"*", "boot"}
  };

在过去,我把解析器写成一个扩展方法,语法类似于LINQ:

public static IEnumerable<IEnumerable<T>> GroupByDelimiter<T>(this IEnumerable<T> input, T delimiter)
{
    var currentList = new List<T>();
    foreach (T item in input)
    {
        if (!item.Equals(delimiter))
        {
            currentList.Add(item);
        }
        else
        {
            yield return currentList;
            currentList = new List<T> {item};
        }
    }
    // return the last list
    yield return currentList;
}

这工作得很好,但我想知道如果这个方法GroupByDelimiter可以使用现有的LINQ扩展方法重写。更好的是,是否有一些我不知道的LINQ方法已经做到了这一点?

使用condition作为分组分隔符有一种奇特的方式。

var input = new[] {"moo", "*", "foo", "bar", "baz", "*", "roo", 
                   "moo", "*", "*", "hoot", "*", "boot"};
    int index = 0;
    var output = input.Select( x => new
                 {
                   Item=x, 
                   GroupCondition = x =="*" ? ++index:index     // Introduce GroupCondition, Increase it if delimiter is found      
                 })
          .GroupBy((x)=>x.GroupCondition)                      // Group by GroupCondition
          .Select( x => x.Select( y => y.Item));                // Get rid of GroupCondition

演示

演示输出

moo
* foo bar baz
* roo moo
*
* hoot
* boot

相关内容

  • 没有找到相关文章

最新更新