将一个 IEnumerable 拆分为多个 IEnumerable



我是linq的新手,我需要根据指标将Couple(字符串文本,布尔指标(类型的IEnumerable拆分为多个IEnumerable,我尝试使用skipwhile和TakeWhile,但没有找到解决方案,输入如下:

Couple("a",false)
Couple("b",false)
Couple("c",true),
Couple("d",false)
Couple("e",false)
Couple("f",true),
Couple("g",true),
Couple("h",true),
Couple("i",false)
Couple("j",true),
Couple("k",true),
Couple("l",false)
Couple("m",false)

结果应该是 7 个 IEnumerables

list1: Couple("a",false)
Couple("b",false)
list2: Couple("c",true)
list3: Couple("d",false)
Couple("e",false)
list4: Couple("f",true)
Couple("g",true)
Couple("h",true)
list5: Couple("i",false)
list6: Couple("j",true)
Couple("k",true)
list7: Couple("l",false) 
Couple("m",false)

请帮忙吗?

试试这个:

public static IEnumerable<IList<Couple>> Split(IEnumerable<Couple> couples)
{
using (var enumerator = couples.GetEnumerator())
{
if (!enumerator.MoveNext())
{
yield break;
}
var current = enumerator.Current;
var group = new List<Couple> { current };
while (enumerator.MoveNext())
{
var next = enumerator.Current;
if (current.Indicator.Equals(next.Indicator))
{
group.Add(next);
}
else
{
yield return group;
group = new List<Couple> { next };
}
current = next;
}
yield return group;
}
}

例:

var couples = new List<Couple> 
{
new Couple("a",false),
new Couple("b",false),
new Couple("c",true),
new Couple("d",false),
new Couple("e",false),
new Couple("f",true),
new Couple("g",true),
new Couple("h",true),
new Couple("i",false),
new Couple("j",true),
new Couple("k",true),
new Couple("l",false),
new Couple("m",false),
};
var groupNr = 1;
foreach (var couplesGroup in Split(couples))
{
Console.WriteLine($"List {groupNr++}: ");
foreach (var couple in couplesGroup)
{
Console.WriteLine($"{couple.Text, 10}, {couple.Indicator}");
}
Console.WriteLine();
}

这是用于拆分序列的通用扩展方法。它需要一个检查两个连续元素的函数,并确定是否应该拆分这些元素。true的结果意味着拆分元素。false的结果意味着不要拆分元素,而是将它们放在同一个子序列中。

public static class EnumerableExtensions
{
/// <summary>Splits a sequence to subsequences according to a specified
/// predicate.</summary>
/// <param name="splitPredicate">A function to determine if two consecutive
/// elements should be split.</param>
public static IEnumerable<TSource[]> SplitByPredicate<TSource>(
this IEnumerable<TSource> source,
Func<TSource, TSource, bool> splitPredicate)
{
var enumerator = source.GetEnumerator();
bool finished = false;
TSource previous = default;
using (enumerator)
{
if (!enumerator.MoveNext()) yield break;
while (!finished)
{
yield return GetSubsequence().ToArray();
}
}
IEnumerable<TSource> GetSubsequence()
{
while (true)
{
yield return enumerator.Current;
previous = enumerator.Current;
if (!enumerator.MoveNext()) { finished = true; break; }
if (splitPredicate(previous, enumerator.Current)) break;
}
}
}
}

使用示例:

var subsequences = couples.SplitByPredicate(
(x, y) => x.Indicator != y.Indicator);

下面是一个没有 Linq 的解决方案:

class Program
{
public class Couple
{
public string Text;
public bool Indicator;
public Couple(string text, bool indicator)
{
Text = text;
Indicator = indicator;
}
}
static void Main(string[] args)
{
var list = new List<Couple>();
list.Add(new Couple("a", false));
list.Add(new Couple("b", false));
list.Add(new Couple("c", true));
list.Add(new Couple("d", false));
list.Add(new Couple("e", false));
list.Add(new Couple("f", true));
list.Add(new Couple("g", true));
list.Add(new Couple("h", true));
list.Add(new Couple("i", false));
list.Add(new Couple("j", true));
list.Add(new Couple("k", true));
list.Add(new Couple("l", false));
list.Add(new Couple("m", false));
var result = new List<List<Couple>>();
int index = 0;
bool last = list[0].Indicator;
result.Add(new List<Couple>());
foreach ( var item in list )
{
if ( item.Indicator != last )
{
index++;
result.Add(new List<Couple>());
}
last = item.Indicator;
result[index].Add(item);
}
for ( index = 0; index < result.Count; index++ )
{
Console.WriteLine($"List n°{index}");
foreach ( var item in result[index] )
Console.WriteLine($"  text: {item.Text}");
}
Console.WriteLine("");
Console.ReadKey();
}

最新更新