2012-07-20 70 views
0

考虑以下情况:如何管理原始对象之间的数据依赖关系?

items = [ 
    { 
    id: 1 
    attributes: [ 
     { key: a, value: 2 } 
     { key: b, value: 3 } 
    ], 
    requirements: null 
    } 
    { 
    id: 2 
    attributes: [ 
     { key: b, value: 2 } 
    ], 
    requirements: a > 2 
    } 
    { 
    id: 3 
    attributes: [ 
     { key: a, value: 1 } 
     { key: c, value: 1 } 
    ], 
    requirements: a > 1 and b > 2 
    } 
    { 
    id: 4 
    attributes: [ 
     { key: a, value: 2 } 
     { key: d, value: 7 } 
    ], 
    requirements: b > 5 and h < 10 
    } 
] 

预期的结果,相加(总和)的各种attributes是:在对象之间

result = [ 
    { key: a, value: 3 } 
    { key: b, value: 5 } 
    { key: c, value: 1 } 
] 

正如你可以看到,有依赖关系(requirements)名单。特别是,因为从不检查条件b > 5 and h < 10,所以id: 4(系列中的最后一个)的对象从计算中被丢弃。相反,具有id: 2的对象最初被丢弃,然后作为id: 3(通过将属性a加上1,使条件为a > 2)的对象的结果落入计算中。

获得具有N个对象的所需结果所需的算法是什么?

声明:所提出的结构只是一个例子。您可以建议您相信实现结果的任何更改。我正在使用JavaScript(CoffeeScript)编程语言,但其他任何都可以。

+0

您是否有时间或空间复杂性要求?显而易见的解决方案是'O(n^2)' - 你放弃了这个选择吗?另外,你需要一些方法来存储需求(当'items'被实例化时,你的当前代码将评估它们为布尔值,所以它们不能被重新检查。你解决了这个问题,还是它也是你问题的一部分? – 2012-07-20 17:40:49

+0

@AaronDufour对'需求'键的评估并不打算在对象实例化上进行,而是在每次被称为'sum'方法时进行;我认为有必要在每个项目的需求之间建立某种联系条件和'sum'过程(一个事件驱动的方法?):每个对象都应该监听数组中的变化(item add/remove),并且如果符合条件,则将其状态更改为'active = true'(或然后list对象再次执行'sum',最终导致其他对象激活,等等。无论如何,这只是一个想法。 – Jerus 2012-07-23 09:44:31

回答

0

让我们开始以我们可以使用的格式获取数据。我们需要能够测试随意的要求,而不是只有当数据对象实例化:

{ 
    id: 4 
    attributes: [ 
     { key: a, value: 2 } 
     { key: d, value: 7 } 
    ], 
    requirements: (sum) -> sum.b > 5 and sum.h < 10 
    } 

虽然我们在这,让我们的属性在一个更有用的状态(注意,这ISN”牛逼绝对必要的,但让一切更简单):

{ 
    id: 4 
    attributes: { 
     a: 2 
     d: 7 
    }, 
    requirements: (sum) -> sum.b > 5 and sum.h < 10 
    } 

现在我会去通过天真的算法,这是最简单的,应该满足您的需求。本质上,我们将继续循环数据集,测试每个尚未使用的数据集,并在数据集通过时将其添加到总和中。

changed = true 
sum = {} 
init(sum, items) 
while changed 
    changed = false 
    for item in items 
     if !item.used && item.requirements(sum) 
      add(sum, item.attributes) 
      changed = true 
      item.used = true 

我会让你在addinit功能填补。 add一个应该是简单的;它将第二个参数中的每个元素添加到第一个元素中的每个元素。 init需要将sum中的每个元素设置为0,这些元素可能会被使用(测试或添加到)。

+0

感谢您提供宝贵的建议和详细的解释。事件驱动实现解决这个问题,但你的方法无疑更聪明和优雅。所以代码少,复杂度低。再次感谢。 – Jerus 2012-07-26 08:46:31