Я собираюсь продолжить ответ Кевина с хорошим решением на основе linq.
Исходный код эффективно рассчитал двумерный логический массив, указывающий, существовала ли координата в myList
в x
и y
координатах для каждого элемента массива.
Тест, используемый для каждого x
& y
, можно выразить в виде лямбда-функции следующим образом:
Func<int, int, bool> original =
(x, y) =>
myList.Exists(item => item.XCoord == x && item.YCoord == y);
Это неэффективно, так как вызывается метод Exists
, и, следовательно, список повторяется для каждой проверенной координаты x
& y
. Будет ли повторяться весь список или нет, зависит от того, найдено или нет совпадение. Во многих случаях совпадений не будет, поэтому весь список посещают несколько раз.
Поэтому лучше предварительно вычислить словарь словарей, чтобы определить, существует ли координата в myList
для любой x
& y
координаты.
var xyLookup =
(from item in myList
group item by item.XCoord into XCoords
select new
{
X = XCoords.Key,
YLookup = (from x in XCoords
group x by x.YCoord into YCoords
select new
{
Y = YCoords.Key,
Coords = YCoords
}).ToDictionary(a => a.Y, a => a.Coords)
}).ToDictionary(b => b.X, b => b.YLookup);
xyLookup
теперь позволяет следующей лямбда-функции заменить оригинальную версию.
Func<int, int, bool> refactored =
(x, y) =>
xyLookup.ContainsKey(x) && xyLookup[x].ContainsKey(y);
Предварительное вычисление xyLookup
занимает некоторое время, поэтому, согласно моим тестам, если у меня массив 3х3, а myList
содержит 3 координаты, то оба метода примерно одинаковы. Я ожидаю, однако, что фактический размер массива и количество элементов в myList
будет намного больше на практике.
Если у меня есть массив 100x100 с 10000 координат в myList
, тогда xyLookup
примерно в 91 раз быстрее, чем оригинальный метод.
Я люблю linq ...: -)