Я бы некоторые идеи о двух решений задачи, здесь оригинальный класс , лишенный лишних подчеркиваний. Обычно идентификатор является уникальным, так чтения и я позаимствовал Distance метод от @ ответа CommuSoft, как он прав насчет этого метода:
class Point
{
public readonly int id;
public float x;
public float y;
public Point(int id, float x, float y)
{
this.id = id;
this.x = x;
this.y = y;
}
public float Distance(Point p)
{
float dx = this.x - p.x;
float dy = this.y - p.y;
return (float)Math.Sqrt(dx * dx + dy * dy);
}
}
Shared часть:
List<Point> list = new List<Point>();
list.Add(new Point(0, 10.0f, 1.0f));
list.Add(new Point(1, 1.0f, 0.0f));
list.Add(new Point(2, 0.0f, 0.0f));
Point p = new Point(3, 0.6f, 0.0f);
Следующая решение IpavluVersionA1 İŞ наиболее эффективными в использовании памяти/распределения и вычислительной эффективностью:
//VersionA1, efficient memory and cpu usage
Point closest_to_p = null;
float shortest_d = float.MaxValue;
//list.ForEach because it is iterating list through for cycle, most effective
list.ForEach(point =>
{
//Distance is computed only ONCE per Point!
var d = point.Distance(p);
if (d > 1.0f) return;
if (closest_to_p == null || shortest_d > d)
{
closest_to_p = point;
shortest_d = d;
}
});
//closest_to_p is cloases point in range with distance 1.0
//or below or is null, then does not exist
Следующие один IpavluVersionA2, лучшее исполнение мудро:
//VersionA2, most efficient memory and cpu usage
Point closest_to_p = null;
float shortest_d = float.MaxValue;
int max = list.Count;
for (int i = 0; i < max; ++i)
{
var point = list[i];
var d = point.Distance(p);
if (d > 1.0f) continue;
if (closest_to_p == null || shortest_d > d)
{
closest_to_p = point;
shortest_d = d;
}
}
//closest_to_p is closest point in range with distance 1.0
//or below or is null, then does not exist
Другое решение, IpavluVersionB, который использует LINQ подход, должно создать новую структуру объект, для того, чтобы сохранить точку и расстояние, но они скорее всего, созданы в стеке. Вычисление расстояния выполняется только один раз, тогда значение используется повторно!
//versionB
var null_point = new KeyValuePair<Point,float>(null, float.PositiveInfinity);
var rslt_point =
list
.Select(xp =>
{
var d = xp.Distance(p);
return d <= 1.0f ? new KeyValuePair<Point, float>(xp, d) : null_point;
})
.Aggregate(null_point, (a, b) =>
{
if (a.Key == null) return b;
if (b.Key == null) return a;
return a.Value > b.Value ? b : a;
}, x => x.Key);
rslt_point
является нулевым или экземпляр самой близкой точке к p
.
ЭТАЛОН:
- должен быть построен в режиме выпуска,
- должен работать без отладки, вне VisualStudio,
- тест работает в 5 раз для двух сценариев,
- сценарий X : 3 предмета, 10 миллионов раз, все методы, время в милисекундах,
- сценарий Y: 3mil itmes, 1 раз, все методы, время в миллисекундах,
the code is here
BechmarkREsults:
- B - число итераций над списком,
- I - количество элементов в списке,
- все числа в миллисекундах,
- CommuSoft - это решение из ответа CommuSoft,
- Ivan Stoev предложил решение с анонимными типами, ведет себя аналогично VersionA2 со структурой,
- Ясно, что IpavluVersionA2 - лучшая производительность.
В [10000000] Я [3]: CommuSoft: 3521 IpavluA1: 371 IpavluA2: 195 IpavluB: 1587
В [10000000] Я [3]: CommuSoft: 3466 IpavluA1: 371 IpavluA2: 194 IpavluB: 1583
В [10000000] Я [3]: CommuSoft: 3463 IpavluA1: 370 IpavluA2: 194 IpavluB: 1583
В [10000000] Я [3]: CommuSoft: 3465 IpavluA1: 370 IpavluA2: 194 IpavluB: 1582
B [10000 000] Я [3]: CommuSoft: 3471 IpavluA1: 372 IpavluA2: 196 IpavluB: 1583
В 1 я [3000000]: CommuSoft: 919 IpavluA1: 21 IpavluA2: 17 IpavluB: 75
В 1 I [ 3000000]: CommuSoft: 947 IpavluA1: 21 IpavluA2: 17 IpavluB: 75
В 1 я [3000000]: CommuSoft: 962 IpavluA1: 21 IpavluA2: 17 IpavluB: 75
В 1 я [3000000]: CommuSoft : 969 IpavluA1: 21 IpavluA2: 17 IpavluB: 75
В 1 я [3000000]: CommuSoft: 961 IpavluA1: 21 IpavluA2: 17 IpavluB: 75
Не следует использовать 'Math.Pow' для вычисления квадратов. –
list.OrderBy (x => x.Distance (p)). First() может быть более компактным. – lintmouse
Почему вы используете 'index' в инструкции, вы никогда не используете его нигде, и вы бросаете его в конце. –