我正在寻找一种最有效的方法来在IEnumerable<T> A
中的每一行之前对IEnumerable<T> B
中的所有行进行网格划分。
例如:
A = {A,B}
B = {1,2,3}
网格划分后:
B = {A,1,B,2,A,3}
答案 0 :(得分:7)
没有简单的解决方案,但这样的事情可能有效。模数运算符在这里非常重要,可以用较少的项重复列表中的结果。
public static List<object> Mesh<T1, T2>(IEnumerable<T1> s1, IEnumerable<T2> s2)
{
T1[] array1 = s1.ToArray();
T2[] array2 = s2.ToArray();
int length1 = array1.Length;
int length2 = array2.Length;
int maxLength = Math.Max(length1, length2);
List<object> result = new List<object>();
for (int i = 0; i < maxLength; i++)
{
result.Add(array1[i % length1]);
result.Add(array2[i % length2]);
}
return result.
}
答案 1 :(得分:2)
该解决方案直接使用IEnumerable参数而不初始化它们,并返回IEnumerable。
public IEnumerable<object> Mesh<S,T>(IEnumerable<S> items1, IEnumerable<T> items2){
bool items1Empty;
bool items2Empty;
bool items1Finished = items1Empty = ValidateParameter(items1, "items1");
bool items2Finished = items2Empty = ValidateParameter(items2, "items2");
using(var items1Enumerator = items1.GetEnumerator()){
using(var items2Enumerator = items2.GetEnumerator()){
while(true){
MoveNext(items1Enumerator, ref items1Finished);
MoveNext(items2Enumerator, ref items2Finished);
if(items1Finished && items2Finished)
break;
if(!items1Empty)
yield return items1Enumerator.Current;
if(!items2Empty)
yield return items2Enumerator.Current;
}
}
}
}
private bool ValidateParameter<T>(IEnumerable<T> parameter, string parameterName){
if(parameter == null)
throw new ArgumentNullException(parameterName);
return !parameter.Any();
}
private void MoveNext(IEnumerator enumerator, ref bool finished){
if(!enumerator.MoveNext()){
enumerator.Reset();
enumerator.MoveNext();
finished = true;
}
}
答案 2 :(得分:0)
试试这个,我的第一个猜测
for(int countA = 0, countB = 0; countA < A.Length; countA ++, countB++)
{
if(countB >= B.Length)
{
countB = 0;
}
newList.Add(A[countA]);
newList.Add(B[countB]);
}
答案 3 :(得分:0)
我也想参加派对!由于我非常喜欢LINQ,让我们考虑以下LINQ解决方案(确定它不是那么有效,但是为了好玩):
public static void Main()
{
var a = new[] {1, 2, 3};
var b = new[] {'a', 'b'};
var joined = a.Join(
b,
x => Array.IndexOf(a, x) % b.Length,
y => Array.IndexOf(b, y) % a.Length,
(x, y) => new object[]{ x, y }
);
var flat = joined.SelectMany(x => x);
Console.Write(string.Join(", ", flat));
}
答案 4 :(得分:0)
另一种方法
public static IEnumerable<T> Mesh<T>(this IEnumerable<T> source, params IEnumerable<T>[] others)
{
var enumerators = new[] { source.GetEnumerator() }.Concat(others.Select(o => o.GetEnumerator())).ToList();
var finishes = new bool[enumerators.Count];
var allFinished = false;
while (!allFinished)
{
allFinsihed = true;
for (var i = 0; i < enumerators.Count; i++)
{
IEnumerator<T> enumerator = enumerators[i];
if (!enumerator.MoveNext())
{
finishes[i] = true;
enumerator.Reset();
enumerator.MoveNext(); // Not sure, if we need it here, Reset says: BEFORE the first element
}
yield return enumerator.Current;
if (!finishes[i])
{
allFinished = false;
}
}
}
}
答案 5 :(得分:0)
您可以编写自己的扩展名以提供更大的灵活性。
注意:此答案不会分配大量不必要的内存,并且只列举所有序列一次。
我已经参与了参数检查。
public static IEnumerable<T> Mesh<T>(
this IEnumerable<T> source,
params IEnumerable<T>[] others)
{
if (others.LongLength == 0L)
{
foreach (var t in source)
{
yield return t;
}
yield break;
}
var nullCheck = Array.FindIndex(others, e => e == null);
if (nullCheck >= 0)
{
throw new ArgumentNullException(string.Format(
"Parameter {0} is null, this is not supported.",
++nullCheck),
(Exception)null);
}
var enumerators = new[] { source.GetEnumerator() }
.Concat(others.Select(o => o.GetEnumerator())).ToList();
try
{
var finishes = new bool[enumerators.Count];
var allFinished = false;
while (!allFinished)
{
allFinsihed = true;
for (var i = 0; i < enumerators.Count; i++)
{
if (finishes[i])
{
continue;
}
if (enumerators[i].MoveNext())
{
yield return enumerators[i].Current;
allFinished = false;
continue;
}
finishes[i] = true;
}
}
}
finally
{
foreach (var enumerator in enumerators)
{
enumerator.Dispose();
}
}
}
只要项目具有相同的类型,这将允许您“网格化”任意数量的锯齿状序列。 e.g。
var a = new[] { 'a', 'b', 'c' };
var b = new[] { '1', '2', '3' };
var c = new[] { 'x', 'y' };
var d = new[] { '7', '8', '9', '0' };
var meshed = a.Mesh(b, c, d);
会产生
{ 'a', '1', 'x', '7', 'b', '2', 'y', '8', 'c', '3', '9', '0' }
如果你想混合你可以做的类型
var a = new[] { 'a', 'b', 'c' };
var b = new[] { 1, 2, 3 };
var meshed = a.Cast<object>().Mesh(b.Cast<object>);
产生类似的东西,
{ ('a'), (1), ('b'), (2), ('c'), (3) }