在将“人类可读”数据解析为更方便的数据结构时遇到的一般问题如下:
假设我有一个兄弟元素列表:
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;
}
这很好用,但我想知道是否可以使用现有的LINQ扩展方法重写此方法GroupByDelimiter
。更好的是,有一些我不知道的LINQ方法已经做到了吗?
答案 0 :(得分:1)
使用conditon作为分组分隔符有一种古怪的方式。
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
演示here
演示输出
moo
* foo bar baz
* roo moo
*
* hoot
* boot