数据过滤算法
Posted
技术标签:
【中文标题】数据过滤算法【英文标题】:Algorithm for data filter 【发布时间】:2010-10-19 17:14:11 【问题描述】:你能给我推荐一个过滤数据的算法吗?
我正在使用 javascript 并尝试编写一个过滤器函数来过滤数据数组。我有一个数据数组和一个过滤器数组,所以为了对每个数据应用每个过滤器,我写了 2循环
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 对象(第一行)。 当我进入第二个 for 循环(过滤器循环)时,我有一个过滤器类,它提取当前过滤器将在其上工作的确切字段,并使用数据的适当字段检查过滤器。
所以在我的例子中
foreach(data)
foreach(filter)
//loop one - filter name
// loop two - filter email
// loop three - filter age
当第二个循环结束时,我设置一个标志,表示数据是否已被过滤,并根据它显示数据。
【问题讨论】:
【参考方案1】:您必须向我们提供有关数据和过滤器的确切结构的更多详细信息,才能真正为您提供帮助。过滤器是否用于选择数据子集或修改数据?过滤器在做什么?
也就是说,有一些一般性的建议:
-
少做事。有什么方法可以限制正在处理的数据量?一些可以快速运行并在您执行主循环之前将其减少的预过滤器?
尽快跳出内循环。如果其中一个过滤器拒绝了一个数据,则跳出内部循环并继续前进到下一个数据。如果这是可能的,那么您还应该尝试将最具选择性的过滤器放在第一位。 (这是假设您的过滤器被用于拒绝列表中的项目,而不是修改它们)
在过滤器执行的计算中检查冗余。如果他们每个人都执行一些共享一些子程序的复杂计算,那么也许可以使用memoization或dynamic programming来避免冗余计算。
真的,这一切都归结为第一点,做更少的工作,在所有三个级别的代码。你可以通过限制外循环中的项目来减少工作量吗?通过在特定过滤器之后停止并首先执行最具选择性的过滤器来减少工作量?通过不在每个过滤器内部进行任何冗余计算来减少工作量?
【讨论】:
【参考方案2】:这就是你应该做的。诀窍是优化“使用过滤器检查数据”部分。您需要遍历所有数据并检查所有过滤器 - 您不会比这更快。
避免字符串比较,尽可能使用原生数据模型,尽量减少每遍使用filter
等的数据集。
如果没有进一步的知识,很难为您优化。
【讨论】:
【参考方案3】:您应该对过滤器的应用进行排序,以便优化两件事:昂贵的检查应该排在最后,而消除大量数据的检查应该排在最前面。然后,您应该确保在出现“out”结果时立即停止检查。
【讨论】:
【参考方案4】:如果您的过滤器正在寻找特定值、范围或文本开头,那么 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);
这种方式的过滤速度比嵌套循环快很多。
【讨论】:
【参考方案5】:假设过滤器删除不匹配的数据,我建议您像这样切换两个循环:
foreach(filter)
foreach(data)
check data with filter
通过这样做,第二个过滤器不必处理所有数据,而只处理通过第一个过滤器的数据,依此类推。当然上面的提示(比如最后做昂贵的检查)仍然是正确的,应该额外考虑。
【讨论】:
应该可以。假设您有 1000 个用户。当第一个过滤器删除其中的 500 个时,即减少 500 个,您需要应用第二个过滤器,依此类推。以上是关于数据过滤算法的主要内容,如果未能解决你的问题,请参考以下文章