根据JSON对象的值从数组中选取JSON对象

根据JSON对象的值从数组中选取JSON对象,json,algorithm,sorting,nsarray,Json,Algorithm,Sorting,Nsarray,也许我认为这是错误的,但这里有一个问题: 我有一个NSMutableArray,里面都是JSON对象。每个对象都是这样的,例如,这里有两个: { player = "Lorenz"; speed = "12.12"; }, { player = "Firmino"; speed = "15.35"; } 好的,这很好,这是我从webserver提要获得的动态信息。现在我想要的是假设有22个这样的条目,并且速度不同 我希望有一个计时器,从1.0秒开始,到60.0秒,每秒几次,我希望它抓住所有速

也许我认为这是错误的,但这里有一个问题:

我有一个NSMutableArray,里面都是JSON对象。每个对象都是这样的,例如,这里有两个:

{
player = "Lorenz";
speed = "12.12";
},
 {
player = "Firmino";
speed = "15.35";
}
好的,这很好,这是我从webserver提要获得的动态信息。现在我想要的是假设有22个这样的条目,并且速度不同

我希望有一个计时器,从1.0秒开始,到60.0秒,每秒几次,我希望它抓住所有速度刚刚超过的玩家。例如,如果计时器在12.0时停止,然后在12.5时再次停止,我希望它能抓取所有速度在12.0到12.5之间的玩家的名字,明白吗

显而易见的简单方法是每次计时器关闭时都完全迭代数组,但我希望计时器关闭很多次,比如每秒10次或更多,所以我认为这是一个相当浪费的算法。还有更好的主意吗?我可以尝试改变从Web服务器获取数据的方式,但我不认为这是必要的。

注意:编辑以反映一种正确的理解,即1到60中的数字在该范围内不断递增,而不是在该间隔内的随机数

在进入计时器循环之前,应进行一些常见的预处理:

将速度从字符串预先转换为数值,以便快速比较,而无需每次解析。这是每个项目的O1,用于处理所有项目

将数据放在有序容器中,如排序列表或排序二叉树。这将允许您轻松找到目标范围内的元素。这在日志n上,用于对所有项目进行排序

在第一次迭代中:

使用二进制搜索查找起始索引。我是奥龙。 使用二进制搜索查找结束索引,使用开始索引绑定搜索。 在后续迭代中:

如果每次迭代增加了一个可预测的量,并且列表中元素之间的步长也是一个可预测的量,那么只需根据Pete的注释维护一个指针和增量即可。这将使每次迭代的成本O1只需提前一个固定的数量

如果迭代之间的步骤和/或列表中的条目不可预测,则按照初始情况进行二进制搜索。如果值是单调递增的,正如我现在理解的问题所述,即使它们是不可预测的,您也可以通过像在另一种情况下一样维护索引将其合并到二进制搜索算法中,但如果值是不可预测的,则不必直接从那里恢复迭代,相反,使用记忆索引设置二进制搜索的下限,以便缩小正在搜索的区域。这将使每次迭代的成本为m,其中m是要考虑的剩余元素

总的来说,这产生的算法不比+I log N差,其中I是与前一个算法(即OI*N)相比的迭代次数,并将大部分计算转移到循环之外,而不是在循环内。

注意:编辑以反映一种正确的理解,即1到60中的数字在该范围内不断递增,而不是在该间隔内的随机数

在进入计时器循环之前,应进行一些常见的预处理:

将速度从字符串预先转换为数值,以便快速比较,而无需每次解析。这是每个项目的O1,用于处理所有项目

将数据放在有序容器中,如排序列表或排序二叉树。这将允许您轻松找到目标范围内的元素。这在日志n上,用于对所有项目进行排序

在第一次迭代中:

使用二进制搜索查找起始索引。我是奥龙。 使用二进制搜索查找结束索引,使用开始索引绑定搜索。 在后续迭代中:

如果每次迭代增加了一个可预测的量,并且列表中元素之间的步长也是一个可预测的量,那么只需根据Pete的注释维护一个指针和增量即可。这将使每次迭代的成本O1只需提前一个固定的数量

如果迭代之间的步骤和/或列表中的条目不可预测,则按照初始情况进行二进制搜索。如果值是单调递增的,正如我现在理解的问题所述,即使它们是不可预测的,您也可以通过像在另一种情况下一样维护索引将其合并到二进制搜索算法中,但如果值是不可预测的,则不必直接从那里恢复迭代,相反,使用记忆索引设置二进制搜索的下限,以便缩小正在搜索的区域。这将使每次迭代的成本为m,其中m是要考虑的剩余元素

总的来说,这产生了一个算法,它不是
比+I log N更糟糕,其中I是与以前的算法相比的迭代次数,该算法是OI*N,将大部分计算转移到循环之外,而不是循环内部。

现代计算机每秒可以执行数十亿次运算。即使您的计时器每秒关闭1000次,并且需要处理1000个条目,您仍然可以使用简单的方法

但要回答这个问题,最好的方法是首先根据速度对数据进行排序,然后对速度已经通过的最后一个玩家进行索引。很明显,在开始的时候,指针指向了第一个球员。然后,每次你的计时器关闭时,你都需要处理从该索引开始的一些连续的玩家块。伪代码中的某些内容:

global index = 0;
sort(players); // sort on speed
onTimer = function(currentSpeed) {
    while (index < players.length && players[index].speed < currentSpeed) {
        processPlayer(players[index]);
        ++ index;
    }
}

现代计算机每秒可以进行数十亿次运算。即使您的计时器每秒关闭1000次,并且需要处理1000个条目,您仍然可以使用简单的方法

但要回答这个问题,最好的方法是首先根据速度对数据进行排序,然后对速度已经通过的最后一个玩家进行索引。很明显,在开始的时候,指针指向了第一个球员。然后,每次你的计时器关闭时,你都需要处理从该索引开始的一些连续的玩家块。伪代码中的某些内容:

global index = 0;
sort(players); // sort on speed
onTimer = function(currentSpeed) {
    while (index < players.length && players[index].speed < currentSpeed) {
        processPlayer(players[index]);
        ++ index;
    }
}

如果您在排序列表中保留索引,那么您就知道下一个项目的索引,当下一个限制超过时,将查找该索引,因此不需要进行二进制搜索。谢谢,Pete。我对这个问题有点误解。这种方法在假设元素和输入数量以可预测的方式递增的情况下起作用,但是——如果不是的话——在最坏的情况下,如果您必须一直递增到最后,这种方法不是仍然有效吗?考虑到你不知道跳转的固定数量?。不过,我已经更新了答案,加入了你的建议,只是做了一些修改。如果你像OP示例所示抓取12到12.5之间的所有玩家,你只需从不小于12的玩家的索引中递增,直到找到不小于12.5的玩家;如果OP想要该范围内的所有玩家,而不是该范围内的第一个和最后一个玩家,那么您必须对他们进行迭代。如果22个条目中的20个介于12和12.5之间,该怎么办?使用二进制搜索限制查找该时间间隔上限的时间。对于问题的更大实例,您可以花时间进行直接迭代。您是对的,无论如何,打印出该范围内的所有条目都是打开的,但是返回一个仅引用数组并包含开始索引和结束索引的子视图将是一个更好的选择,特别是如果OP后来将其用于不需要迭代所有项的计算,如查找该子范围内的中值时间。是的,如果OP希望在该范围内的第一个和最后一个,而不是迭代该范围内的所有项,则二进制搜索会更好。如果您在排序列表中保留索引,然后你知道下一个项目的索引,当下一个限制超过时,你可以找到它,所以不需要进行二进制搜索。谢谢,皮特。我对这个问题有点误解。这种方法在假设元素和输入数量以可预测的方式递增的情况下起作用,但是——如果不是的话——在最坏的情况下,如果您必须一直递增到最后,这种方法不是仍然有效吗?考虑到你不知道跳转的固定数量?。不过,我已经更新了答案,加入了你的建议,只是做了一些修改。如果你像OP示例所示抓取12到12.5之间的所有玩家,你只需从不小于12的玩家的索引中递增,直到找到不小于12.5的玩家;如果OP想要该范围内的所有玩家,而不是该范围内的第一个和最后一个玩家,那么您必须对他们进行迭代。如果22个条目中的20个介于12和12.5之间,该怎么办?使用二进制搜索限制查找该时间间隔上限的时间。对于问题的更大实例,您可以花时间进行直接迭代。您是对的,无论如何,打印出该范围内的所有条目都是打开的,但是返回一个仅引用数组并包含开始索引和结束索引的子视图将是一个更好的选择,特别是如果OP后来将其用于不需要迭代所有项的计算,如查找该子范围内的中值时间。是的,如果OP希望在该范围内的第一个和最后一个,而不是迭代该范围内的所有项,则二进制搜索会更好。