我尝试在列表中找到一个具有最接近值的对象 我写了这个:
float target = 100.0f;
int index = int.MaxValue;
float nearest = float.MaxValue;
for(int i = 0; i < objectList.Count; i++)
{
if(Math.Abs(objectList[i].value - target) < nearest)
{
nearest = Math.Abs(objectList[i].value - target);
index = i;
}
}
//do something with objectList[index]
这实际上有效,但是当列表太大时,它会耗费相当多的时间进行搜索。
我知道有可能这样做,但我不知道它是什么。
答案 0 :(得分:2)
您可以通过缓存某些值并反转循环来略微加快速度:
$(modal).on('hide', window[close_function]() );
此外,如果您的对象列表没有太大变化,您可以排序并应用二进制最近搜索,它将在 O(log(n))中运行即可。可以做很多优化。
例如,您可以将所有内容放入已排序的二叉树(例如RB树)并对其进行搜索。它的运行速度比普通外观快得多。当然,只有在此列表中有大量搜索时,这才有效。
其他方法是将数组拆分成批处理并通过 Parallel.For 同时处理它们。然后只处理批次的结果。
答案 1 :(得分:1)
除非您的列表已排序,否则除了检查每个对象之外别无他法。您可以在变量中保存距离,这样您就不会计算两次。
float target = 100.0f;
int index = int.MaxValue;
float nearest = float.MaxValue;
for(int i = 0; i < objectList.Count; i++)
{
float dist = Math.Abs(objectList[i].value - target);
if(dist < nearest)
{
nearest = dist;
index = i;
}
}
答案 2 :(得分:0)
对于没有受过正规教育的开发人员来说,这是非常困难的。 如果您的对象列表已经排序。您可以使用二进制搜索。 如果您首先需要对列表进行排序,那么您将不会节省时间,因为您的方法需要Θ(n log(n))时间并且排序需要Θ(n log(n))时间并且搜索排序列表需要Θ(log(n))时间,这比你的方法慢。
如果您的列表已经排序,例如使用sortedList,则为Buf。 在Θ(log(n))时间内可以使用二进制搜索来查找最近的项目。 (这是令人难以置信的快速)
大问题:二进制搜索会找到一个确切的项目,而不是最接近的项目。这意味着我们需要推出自己的实现。这是一个执行此操作的示例应用程序,函数public T findClosest是我们的二进制搜索实现。
您可以使用它来测试,玩游戏并了解有关递归结构的更多信息。
版权所有2017 Eldar Kersebaum
根据Apache许可证2.0版(&#34;许可证&#34;)获得许可;除非符合许可,否则您不得使用此文件。您可以在
获取许可证副本http://www.apache.org/licenses/LICENSE-2.0 除非适用法律要求或书面同意,否则根据许可证分发的软件将按照“现状”分发。基础,不附带任何明示或暗示的担保或条件。有关管理许可下的权限和限制的特定语言,请参阅许可证。
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace FindingClosestObjectInList
{
class exampleObject
{
public float value;
}
class Program
{
static void Main(string[] args)
{
//Generate objectList with some random value
var objectList = new SortedList<float, exampleObject>();
var rnd = new Random();
for (int i = 0; i < 10000; i++)
{
var o = new exampleObject();
o.value = (float)(rnd.NextDouble());
//Values need to be Unique, that might be a problem for you.
if (!objectList.Keys.Contains(o.value))
{
objectList.Add(o.value, o);
}
}
float target = .314f;
var closestToTarget = objectList.Keys.FindClosest(target);
Console.WriteLine(closestToTarget);
Console.ReadKey();
}
}
public static class ExtensionMethod
{
public static T FindClosest<T>(this IList<T> sortedCollection, T target)
where T : IComparable<T>, IConvertible
{
//Initialize borders for binary search
int begin = 0;
int end = sortedCollection.Count;
T lastElement = target;
while (end > begin)
{
int index = (begin + end) / 2;
lastElement = sortedCollection[index];
//Small change to binary search, to make sure we pick the closer one,
//when we two values left.
if (end - begin == 2)
{
//Distanzes between the two values and the
var a = sortedCollection[begin];
var b = sortedCollection[begin + 1];
var aDist = substractGeneric(a, target);
var bDist = substractGeneric(b, target);
return a.CompareTo(b) <= 0 ? a : b;
}
//Actual binary search
if (lastElement.CompareTo(target) >= 0)
end = index;
else
begin = index + 1;
}
//Normal ending of binary search.
return lastElement;
}
//If your Type that doesn't support substraction, this will explode at RUNTIME.
public static T substractGeneric<T>(T a, T b)
where T : IConvertible //Will make it more difficult to call this function with stupid Ts, but might still explode.
{
return (dynamic)a - (dynamic)b;
}
}
}
答案 3 :(得分:-1)
你可以像这样使用linq表达式:
var newList = objectList.Select(i => new { value = i, delta = Math.Abs(i - target) }).OrderByDescending(i=>i.delta);
nearest = (newList.ToArray())[0].value;