C# 混合几个IEnumerable<;T>;在C中输入一个#
我经常需要在我有C# 混合几个IEnumerable<;T>;在C中输入一个#,c#,.net,linq,ienumerable,enumerable,C#,.net,Linq,Ienumerable,Enumerable,我经常需要在我有IEnumerable A,IEnumerable B的地方执行操作,我想创建IEnumerable C,其中C将从A获取2T,然后从B获取1T,然后再从A获取2T,然后从B获取1T,依此类推-aabababaab 在C#中是否有一些语言结构,也许有一些LINQ表达式可以轻松完成 现在,我编写了一个小型助手类,它使我能够: var C=EnumerableMixer(新的int[]{2,1},A,B): 公共类EnumerableMix:IEnumerable { int[]数量
IEnumerable A
,IEnumerable B
的地方执行操作,我想创建IEnumerable C
,其中C将从A获取2T,然后从B获取1T,然后再从A获取2T,然后从B获取1T,依此类推-aabababaab
在C#中是否有一些语言结构,也许有一些LINQ表达式可以轻松完成
现在,我编写了一个小型助手类,它使我能够:
var C=EnumerableMixer(新的int[]{2,1},A,B)
:
公共类EnumerableMix:IEnumerable
{
int[]数量;
IEnumerable[]Args;
公共EnumerableMixer(int[]数量,params IEnumerable[]参数)
{
这个。数量=数量;
this.Args=Args;
if(quantity.Length!=args.Length)
抛出新的NotImplementedException(“数量必须与参数数量具有相同的长度!”);
}
可数混合
{
得到
{
可用变量=新列表(数量、长度);
变量枚举数=新列表(数量.长度);
对于(int i=0;i0)
{
for(int i=0;i
稍微长一点的解决方案是:
public IEnumerable<TValue> Mix<TValue>(IEnumerable<TValue> a, IEnumerable<TValue> b)
{
var aEnumerator = a.GetEnumerator();
var bEnumerator = b.GetEnumerator();
while (true)
{
if (!aEnumerator.MoveNext())
{
yield break;
}
yield return aEnumerator.Current;
if (!aEnumerator.MoveNext())
{
yield break;
}
yield return aEnumerator.Current;
if (!bEnumerator.MoveNext())
{
yield break;
}
yield return bEnumerator.Current;
}
}
公共IEnumerable混合(IEnumerable a,IEnumerable b)
{
var aEnumerator=a.GetEnumerator();
var bEnumerator=b.GetEnumerator();
while(true)
{
如果(!aEnumerator.MoveNext())
{
屈服断裂;
}
收益率返回分子。当前;
如果(!aEnumerator.MoveNext())
{
屈服断裂;
}
收益率返回分子。当前;
如果(!bEnumerator.MoveNext())
{
屈服断裂;
}
收益率-收益率-当前值;
}
}
此解决方案不会创建不必要的对象。如果您不熟悉yield关键字:这是我的Linq解决方案: 对于每个元素,分配一个索引,然后按正确的顺序获取元素
// for example. You can use with any type
IEnumerable<Int32> listA = new List<Int32>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
IEnumerable<Int32> listB = new List<Int32>() { 101, 102, 103, 104, 105, 106, 107, 108, 109, 110};
// you want 2 of list A and 1 of list B. You can change the values
Int16[] quantity = new Int16[] { 2, 1 };
IEnumerable<Int32> listC = listA.Select((e, i) => new { element = e, index = (i / (quantity[0]) * (quantity[0] + quantity[1]) + (i%quantity[0]))})
.Concat(listB.Select((e, i) => new { element = e, index = (i / (quantity[1]) * (quantity[0] + quantity[1]) + (i%quantity[1]) + quantity[0])}))
.OrderBy(e => e.index)
.Select(e => e.element);
关于第二份清单:
index = i/(quantity[1]) * (quantity[0]+quantity[1]) + (i%quantity[1]) + quantity[0]
版本1
这是基于adhie的解决方案。它将比率考虑在内,并在退出该方法之前完全完成这两个序列。标志
用于跟踪最后一个循环是否产生任何结果。当标志
为false时,两个序列都将耗尽
public IEnumerable<T> Mix<T>(IEnumerable<T> sequenceA, IEnumerable<T> sequenceB, int ratioA, int ratioB)
{
var etorA = sequenceA.GetEnumerator();
var etorB = sequenceB.GetEnumerator();
bool flag = true;
while(flag)
{
flag = false;
for(int i = 0; i < ratioA && (flag |= etorA.MoveNext()); i++)
yield return etorA.Current;
for(int i = 0; i < ratioB && (flag |= etorB.MoveNext()); i++)
yield return etorB.Current;
}
}
public IEnumerable Mix(IEnumerable sequenceA、IEnumerable sequenceB、int ratioA、int ratioB)
{
var etorA=sequenceA.GetEnumerator();
var etorB=sequenceB.GetEnumerator();
布尔标志=真;
while(旗帜)
{
flag=false;
对于(inti=0;i
版本2
与版本1几乎相同,但采用可变数量的序列
public IEnumerable<T> Mix<T>(params KeyValuePair<IEnumerable<T>, uint>[] quantifiedSequences)
{
var sequences = quantifiedSequences.Select(x => new { Etor = x.Key.GetEnumerator(), Quantity = x.Value });
bool flag = true;
while(flag)
{
foreach (var sequence in sequences)
for(int i = 0; i < sequence.Quantity && (flag |= sequence.Etor.MoveNext()); i++)
yield return sequence.Etor.Current;
}
}
public IEnumerable混合(参数KeyValuePair[]quantifiedSequences)
{
var sequences=quantifiedSequences.Select(x=>new{Etor=x.Key.GetEnumerator(),Quantity=x.Value});
布尔标志=真;
while(旗帜)
{
foreach(序列中的var序列)
对于(int i=0;i
我不知道为什么这会被否决(除非我错过了什么),这是我在看到OP实现了一个更复杂的版本之前要提出的建议。我不知道你的答案,但它没有选择将2-1比率设置为函数参数,这就是为什么它更简单的原因。当其中一个完成时,它也会破裂,而我的会完成所有的,不确定哪一个更好。请注意,我的解决方案支持两个以上的ienumerables的组合。@watbywbarif那么你应该在你的需求中解释一下,而不是说你想要一个枚举,其中一个对另一个迭代两个对象。对不起,这只是个例子,如果你看问题,它清楚地说明了几个,从我的助手类中,你可以看到我启用了几个枚举数和每个枚举数的自定义样本数。我也没有说这个解决方案不好,它对我的情况来说是可行的,但在最后,当你比较两个解决方案时,如果两个解决方案都能正常工作,你会考虑一些额外的因素,比如哪个会表现更好,哪个更一般,或者。。。我同意这里不需要像我在解决方案中那样使用OP,因为静态函数的性能更好,代码更短更简单,但这很容易改变。应该怎么办
public IEnumerable<T> Mix<T>(IEnumerable<T> sequenceA, IEnumerable<T> sequenceB, int ratioA, int ratioB)
{
var etorA = sequenceA.GetEnumerator();
var etorB = sequenceB.GetEnumerator();
bool flag = true;
while(flag)
{
flag = false;
for(int i = 0; i < ratioA && (flag |= etorA.MoveNext()); i++)
yield return etorA.Current;
for(int i = 0; i < ratioB && (flag |= etorB.MoveNext()); i++)
yield return etorB.Current;
}
}
public IEnumerable<T> Mix<T>(params KeyValuePair<IEnumerable<T>, uint>[] quantifiedSequences)
{
var sequences = quantifiedSequences.Select(x => new { Etor = x.Key.GetEnumerator(), Quantity = x.Value });
bool flag = true;
while(flag)
{
foreach (var sequence in sequences)
for(int i = 0; i < sequence.Quantity && (flag |= sequence.Etor.MoveNext()); i++)
yield return sequence.Etor.Current;
}
}