我有一个日志分析脚本来填充复杂的可视化。
描绘一个活动对象的数组(称为非常原始的'log'),每个对象的格式如下:
{
name:foo,
activities:[
{time:t, action:a},
{time:t, action:a},
{time:t, action:a},
...
]
}
阵列中最多有75个活动对象,每个活动对象包含400-600个动作的数组(自前一天午夜起每5分钟一个时段)。
如果已知活动名称(上面的foo)和活动数组中已存在的时间,我需要更新相关的操作。
每个名称都是唯一的,每次在数组中按升序排列,精确增加5分钟。
每次更新图表时我必须做1000多次这样的事情(所以平均需要更新1000个值,1000 * 500 * 60点才能绘图),性能是一个相当关键的问题... < / p>
在jq中循环远比我能写的任何东西都高效,所以目前我已经
了n = "foo";
t = new Date(y,mm,d,h,m).toLocaleString() // matches a time stamp in the log
$.grep($.grep(log, function(n, i)
{
return (n.name == n)
}
)[0].activities, function(n, i)
{
return (n.time == t)
}
)[0].action = "bar";
这似乎有效,但这花了我很长时间,我和自己有太多争论,我不自信。
我错过了更好的方法吗?
答案 0 :(得分:2)
我不会为您的问题提供更好的loop method
,因为您提出的任何循环相对都不会比最后一个更好。
如果您真的想要一个可以提高性能的解决方案,那么您应该考虑完全重新排列对象。如果每个日志的每个name
和每个活动数组的time
都是唯一的,则可以更改对象设置,使其值为the key of each subobject
。
使用这种方法,你只需要进行按键查找,不需要循环。
新LOG对象
var log =
{
unique_name : {
"activities" : {
time_1 : action_1,
time_2 : action_2,
time_3 : action_3,
etc...
}
},
unique_name_2 : {
"activities" : {
etc...
}
}
}
现在使用var u_name = "foo";
和var t = "some time";
,您只需执行...
log[u_name][t] = "some action";
希望这有帮助!
答案 1 :(得分:1)
好像你想要第一个匹配日志的第一个匹配活动。
在这种情况下,您应该在找到第一个匹配后中断循环。您可以使用.some()
。
n = "foo";
t = new Date(y,mm,d,h,m).toLocaleString() // matches a time stamp in the log
log.some(function(ob, i) {
if (ob.name == n) {
ob.activities.some(function(ob2, i) {
if (ob2.time == t) {
ob2.action = "bar";
return true;
}
});
return true;
}
});
此外,您的n
参数遮蔽了您的n
变量,因此我将参数更改为ob
。
但for
循环通常比功能方法快一点。
n = "foo";
t = new Date(y,mm,d,h,m).toLocaleString() // matches a time stamp in the log
for (var i = 0; i < log.length; i++) {
var ob = log[i];
if (ob.name == n) {
for (var j = 0; j < ob.activities.length; j++) {
var ob2 = ob.activities[j];
if (ob2.time == t) {
ob2.action = "bar";
break;
}
}
break;
}
}
如果您认为如果内循环上找不到匹配项,您应该保持外循环,请将代码更改为以下之一:
n = "foo";
t = new Date(y,mm,d,h,m).toLocaleString() // matches a time stamp in the log
log.some(function(ob, i) {
if (ob.name == n) {
return ob.activities.some(function(ob2, i) {
if (ob2.time == t) {
ob2.action = "bar";
return true;
}
});
}
});
n = "foo";
t = new Date(y,mm,d,h,m).toLocaleString() // matches a time stamp in the log
OUTER:
for (var i = 0; i < log.length; i++) {
var ob = log[i];
if (ob.name == n) {
for (var j = 0; j < ob.activities.length; j++) {
var ob2 = ob.activities[j];
if (ob2.time == t) {
ob2.action = "bar";
break OUTER;
}
}
}
}