2

你能给我推荐一个过滤数据的算法吗?

我正在使用 javascript 并尝试编写一个过滤器函数来过滤一个数据数组。我有一个数据数组和一个过滤器数组,所以为了对每个数据应用每个过滤器,我编写了 2 个 for 循环

foreach(data)
{
  foreach(filter)
  {
   check data with filter
  }
}

这不是正确的代码,但简而言之,我的功能是做什么的,问题是这需要大量时间,有人可以提出更好的方法。

我正在使用 Mootools 库,数据数组是 JSON 数组

数据和过滤器的详细信息

数据是让我们说用户的 JSON 数组,所以它将是

data = [{"name" : "first", "email" :  "first@first", "age" : "20"}.
        {"name" : "second", "email" :  "second@second", "age" : "21"}
        {"name" : "third", "email" :  "third@third", "age" : "22"}]

过滤器数组基本上是针对不同数据字段的自定义类

alFilter[0] = filterName;
alFilter[1] = filterEmail;
alFilter[2] = filterAge;

因此,当我进入第一个 for 循环时,在上述情况下,我得到了一个 JSON opbject(第一行)。当我进入第二个 for 循环(过滤器循环)时,我有一个过滤器类,它提取当前过滤器将在其上工作的确切字段,并使用数据的适当字段检查过滤器。

所以在我的例子中

foreach(data)
{
 foreach(filter)
{
  //loop one - filter name
 // loop two - filter email
 // loop three - filter age
}
}

当第二个循环结束时,我设置一个标志,表示数据是否已被过滤,并根据它显示数据。

4

5 回答 5

3

您将不得不向我们提供有关数据和过滤器的确切结构的更多详细信息,才能真正为您提供帮助。过滤器是否用于选择数据子集或修改数据?过滤器在做什么?

也就是说,有一些一般性建议:

  1. 少做点工作。有什么方法可以限制正在处理的数据量?一些可以快速运行并在您执行主循环之前将其减少的预过滤器?
  2. 尽快跳出内循环。如果其中一个过滤器拒绝了一个数据,则跳出内部循环并继续前进到下一个数据。如果这是可能的,那么您还应该尝试将最具选择性的过滤器放在第一位。(这是假设您的过滤器被用于拒绝列表中的项目,而不是修改它们)
  3. 检查过滤器执行的计算中的冗余。如果他们每个人都执行一些共享一些子程序的复杂计算,那么也许可以使用记忆动态编程来避免冗余计算。

真的,这一切都归结为第一点,在代码的所有三个级别上做更少的工作。你可以通过限制外循环中的项目来减少工作量吗?通过在特定过滤器之后停止并首先执行最具选择性的过滤器来减少工作量?通过不在每个过滤器内部进行任何冗余计算来减少工作量?

于 2009-04-15T21:20:01.510 回答
2

你应该这样做。诀窍是优化“使用过滤器检查数据”部分。您需要遍历所有数据并检查所有过滤器 - 您不会比这更快。

避免字符串比较,尽可能使用原生数据模型,尝试使用 减少每次传递的数据集filter,等等。

如果没有进一步的知识,很难为您优化它。

于 2009-04-15T21:20:28.483 回答
2

您应该对过滤器的应用程序进行排序,以便优化两件事:昂贵的检查应该排在最后,而消除大量数据的检查应该排在最前面。然后,您应该确保一旦出现“输出”结果,检查就被缩短了。

于 2009-04-15T23:32:05.563 回答
1

如果您的过滤器正在寻找特定值、范围或文本开头,那么 jOrder ( http://github.com/danstocker/jorder ) 将适合您的问题。

您需要做的就是创建一个 jOrder 表,如下所示:

var table = jOrder(data)
    .index('name', ['name'], { grouped: true, ordered: true })
    .index('email', ['email'])
    .index('age', ['age'], { grouped: true, ordered: true, type: jOrder.number });

然后调用table.where()过滤表。

当您正在寻找完全匹配时:

filtered = table.where([{name: 'first'}, {name: 'second'}]);

当您正在寻找某个字段的某个范围时:

filtered = table.where([{age: {lower: 20, upper: 21}}], {mode: jOrder.range});

或者,当您查找以给定字符串开头的值时:

filtered = table.where([{name: 'fir'}], {mode: jOrder.startof});

与嵌套循环相比,这种方式的过滤速度要快很多。

于 2010-07-14T09:53:08.260 回答
0

假设过滤器删除不匹配的数据,我建议您像这样切换两个循环:

foreach(filter) {
    foreach(data) {
        check data with filter
    }
}

通过这样做,第二个过滤器不必处理所有数据,而只处理通过第一个过滤器的数据,依此类推。当然,上面的提示(比如最后做昂贵的检查)仍然是正确的,应该另外考虑。

于 2009-04-16T14:53:17.807 回答