1

我有一个日志分析脚本来填充复杂的可视化。

想象一个 Activity 对象的数组(称为“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 点),性能是一个相当关键的问题......

在 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";

这似乎奏效了,但我花了这么长时间,而且我和自己发生了很多争论,以至于我没有信心。

我错过了更好的方法吗?

4

2 回答 2

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";

希望这可以帮助!

于 2013-03-14T05:55:56.900 回答
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;
          }
      }
  }
}
于 2013-03-14T05:46:02.447 回答