2013-03-14 112 views
1

我有一个日志分析脚本来填充复杂的可视化。使用jquery搜索对象数组

图片的阵列(称为,而unoriginally,“登录”)活动的对象,其中每一个是在以下形式:在阵列中

{ 
name:foo, 
activities:[ 
      {time:t, action:a}, 
      {time:t, action:a}, 
      {time:t, action:a}, 
      ... 
      ] 
} 

将有高达75的活动对象,每片含一系列400-600个动作(从前一天的午夜开始每隔5分钟一个时隙)。

给定一个已知的活动名称(上面的foo)和活动数组中已经存在的时间,我需要更新关联的动作。

每个名称都是唯一的,每次在数组中以5分钟的增量升序排列。

因为每次更新图表时(因此平均需要更新1000个值和1000 * 500 * 60点图表),我必须要做1000次以上的操作,所以性能是一个相当关键的问题。

在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

*“在JQ循环是远远超过任何我能写......更有效的” *为什么地球上,你认为呢? – 2013-03-14 05:35:32

+0

你可以给时间序列的样本值 – 2013-03-14 05:35:35

+0

在本地格式如所有字符串“2013年3月13日上午09时40分○○秒” – PerryW 2013-03-14 05:53:22

回答

2

我不会给你更好的loop method为你的问题米,因为你想出的任何回路将相对不会比最后一个更好。

如果您真的想要一个能够提高性能的解决方案,那么您应该考虑彻底重新整理对象。如果每个活动数组的每个日志和time的每个name都是唯一的,则可以更改对象设置以使这些值为the key of each subobject

使用这种方法,你只在做一键查找,没有循环需要。

新的日志对象

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

好像你想要第一个匹配的日志的第一个匹配的活动。

在这种情况下,您应该在找到第一个匹配项后打破循环。你可以用.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; 
      } 
     } 
    } 
} 
+0

嗯......这与我几个小时以前的事情没有任何的距离,我猜想缺乏信心--JQuery很容易成为一个安全保护毯:) – PerryW 2013-03-14 05:57:41

+0

@PerryW:关键是要停止尽快循环*(假设您只对每个数组的第一个结果感兴趣)*。你确定你想要在第一场比赛中总是想停止外部阵列吗?就像如果内部数组没有找到匹配,你要保持外阵去,或者是在外部阵列中的所有项目独特之处? – 2013-03-14 06:00:53

+0

...无论如何,我更新了我的答案来说明如何做到这一点,如果外环应继续在没有匹配的内循环中找到。 – 2013-03-14 06:07:26