Можно иметь один цикл, но вы будете обрабатывать некоторую часть каждого массива более одного раза.
public static void JustDoIt(double[] x, double[] y)
{
Array.Sort(x);
Array.Sort(y);
bool mustContinue = true;
bool isXTurns;
bool withinTolerance;
int lastBase_x = 0;
int lastBase_y = 0;
int lastMatch_x = 0;
int lastMatch_y = 0;
int current_x = 0;
int current_y = 0;
int matchedCount_x = 0;
int matchedCount_y = 0;
double yourTolerance = 0.001;
while (mustContinue)
{
isXTurns = x[current_x] <= y[current_y];
if (isXTurns)
{
withinTolerance = (y[current_y] - x[current_x] <= yourTolerance);
}
else
{
withinTolerance = (x[current_x] - y[current_y] <= yourTolerance);
}
if (withinTolerance)
{
if (isXTurns)
{
if (current_x > lastMatch_x)
{
matchedCount_x++;
lastMatch_x = current_x;
}
if (current_y > lastMatch_y)
{
matchedCount_y++;
lastMatch_y = current_y;
}
if (current_y + 1 < y.Length)
{
current_y++;
}
else if (current_x + 1 < x.Length)
{
current_x++;
}
else
{
mustContinue = false;
}
}
else
{
if (current_y > lastMatch_y)
{
matchedCount_y++;
lastMatch_y = current_y;
}
if (current_x > lastMatch_x)
{
matchedCount_x++;
lastMatch_x = current_x;
}
if (current_x + 1 < x.Length)
{
current_x++;
}
else if (current_y + 1 < y.Length)
{
current_y++;
}
else
{
mustContinue = false;
}
}
}
else
{
if (isXTurns)
{
lastBase_x++;
mustContinue = lastBase_x < x.Length;
}
else
{
lastBase_y++;
mustContinue = lastBase_y < y.Length;
}
current_x = lastBase_x;
current_y = lastBase_y;
}
}
}
Некоторые странные результаты, которые вы получите: если у вас есть 2 массива по 2 элемента в каждом, возможно, что у вас более двух совпадений от x до y или от y до x.Это происходит потому, что x [0] может совпадать с y [0] и y [1], так же как и x [1].Таким образом, вы получите 4 матча в обоих «направлениях».Например, когда я запускал этот код с двумя массивами по 1000 элементов в каждом, у меня было 1048 совпадений в одном и 978 совпадений в другом.Я надеюсь, что это поможет.
Редактировать : Вот общая версия:
public static void JustDoIt<T>(IEnumerable<T> items_x, IEnumerable<T> items_y, out int matchedCount_x, out int matchedCount_y, IComparer<T> comparer, Func<T, T, bool> toleranceReferee)
{
T[] x = items_x.OrderBy(item => item, comparer).ToArray();
T[] y = items_y.OrderBy(item => item, comparer).ToArray();
bool mustContinue = true;
bool isXTurns;
bool withinTolerance;
int lastBase_x = 0;
int lastBase_y = 0;
int lastMatch_x = 0;
int lastMatch_y = 0;
int current_x = 0;
int current_y = 0;
matchedCount_x = 0;
matchedCount_y = 0;
while (mustContinue)
{
isXTurns = comparer.Compare(x[current_x], y[current_y]) <= 0;
withinTolerance = toleranceReferee(x[current_x], y[current_y]);
if (withinTolerance)
{
if (isXTurns)
{
if (current_x > lastMatch_x)
{
matchedCount_x++;
lastMatch_x = current_x;
}
if (current_y > lastMatch_y)
{
matchedCount_y++;
lastMatch_y = current_y;
}
if (current_y + 1 < y.Length)
{
current_y++;
}
else if (current_x + 1 < x.Length)
{
current_x++;
}
else
{
mustContinue = false;
}
}
else
{
if (current_y > lastMatch_y)
{
matchedCount_y++;
lastMatch_y = current_y;
}
if (current_x > lastMatch_x)
{
matchedCount_x++;
lastMatch_x = current_x;
}
if (current_x + 1 < x.Length)
{
current_x++;
}
else if (current_y + 1 < y.Length)
{
current_y++;
}
else
{
mustContinue = false;
}
}
}
else
{
if (isXTurns)
{
lastBase_x++;
mustContinue = lastBase_x < x.Length;
}
else
{
lastBase_y++;
mustContinue = lastBase_y < y.Length;
}
current_x = lastBase_x;
current_y = lastBase_y;
}
}
}
С примером того, как вы бы назвали его для int:
List<int> x2 = new List<int>() { 2, 4, 4, 6, 9, 9 }; // To test an IEnumerable
IEnumerable<int> y2 = new int[] { 1, 3, 3, 4, 6, 9 }; // To test another
int xcount;
int ycount;
SingleLoop.JustDoIt(
x2,
y2,
out xcount,
out ycount,
Comparer<int>.Default,
(currentX, currentY) => { return currentX == currentY; });