代码之家  ›  专栏  ›  技术社区  ›  Rene Pot

在对象数组中查找具有较大键的元素

  •  0
  • Rene Pot  · 技术社区  · 7 年前

    我正在写一个小的反应式框架,在这里我需要找出哪些订户需要更新。我正在实现深度绑定,我遇到了如何以有效的方式找到订户的难题。

    存储的变量可以是一个对象,例如

    {
        "user": {
            "preferences": {
                "food": "vegetarian"
            }
        }
    }
    

    您可以将内容获取到此变量的任何级别,如下所示

    getVar("user_preferences_food");
    getVar("user_preferences");
    

    但是,您也可以这样更新它

    setVar("user_preferences_food", "meat");
    setVar("user_preferences", {"food": "meat"});
    

    但在第一个setvar的情况下( user_preferences_food )我怎样才能找到使用 getVar("user_preferences"); 甚至 getVar("user"); 最有效。

    我已经通过将VaR拆分为 _ 然后一个接一个地确定下一个级别并合并所有生成的数组。但这是非常资源密集型的。尤其是如果订户很多的话。必须有一种更好的方法来找到资源密集度较低的资源。

    编辑:我遗漏了部分解释。

    还有一个订阅方法

    subscribe("user", cb);
    subscribe("user_preferences", cb);
    subscribe("user_preferences_food", cb);
    

    这些订阅存储在框架中的数组中。

    例如,一旦更新了“用户首选项”食物,就应该触发上面的所有订阅。但显然不是 subscribe('othervar');

    简化订阅方法:

    var subscriptions = [];
    function subscribe(var, callback){
       subscriptions.push({var: var, cb: callback});
    }
    

    简化 getVar

    vars = {};
    getVar(var){
       // find var in vars with this logic: https://stackoverflow.com/a/18937118/249710
    
          // current exact match on subscribers, but need the "parents, grandparents etc here
           var toUpdate = _.where(subscriptions, {
            "var" : var
        });
        _.each(toUpdate, function(sub){ sub.cb();});
    }
    

    存储或获取数据作为我已经介绍过的密钥的一部分。它只是以最有效的方式找到订户

    PS:这是一个我还不能依赖ES6的环境(并非所有用户都启用了ES6),没有DOM,但我确实包含下划线。(钛应用开发平台)

    3 回复  |  直到 7 年前
        1
  •  1
  •   Mad    7 年前

    我会尝试为回调创建一个列表,所以你在一个列表中循环,这样你就不必搜索,因为你知道列表中有所有回调。

    因此,如果您调用set var(“user_prefs”),就用根变量设置一个单独的列表。在本例中,它是用户。

    如果用setvar更改了任何对象(无论深度与否),则转到根var,获取该列表并使用回调在该列表中循环。

    这样做的好处是,您可以用根变量设置一个列表, var cblist[firstvar]这包含所有回调。不搜索只是循环。

    这是MongoDB的原则,数据已经准备好了,您不需要搜索,因为您知道列表已经存在了。

        2
  •  0
  •   Nina Scholz    7 年前

    您可以拆分字符串并使用它来减少对象。

    function getVar(object, path) {
        return path
            .split('_')
            .reduce(function (o, k) {
                return (o || {})[k];
            }, object);
    }
    
    function setVar(object, path, value) {
        var keys = path.split('_'),
            last = keys.pop();
    
        keys.reduce(function (o, k) {
            return o[k] = o[k] || {};
        }, object)[last] = value;
    }
    
    
    var object = { user: { preferences: { food: "vegetarian" } } };
    
    console.log(getVar(object, "user_preferences_food"));
    console.log(getVar(object, "user_preferences"));
    
    setVar(object, "user_preferences_food", "meat");
    console.log(object);
    
    setVar(object, "user_preferences", {"food": "meat"});
    console.log(object);
    .as-console-wrapper { max-height: 100% !important; top: 0; }
        3
  •  0
  •   Rene Pot    7 年前

    我最终做了这个:

    var options = [];
    var parts = key.split('_');
    var string = parts[0];
    _.each(parts, function(p, i){
        if (i > 0) string += '_' + p;
        options.push(string);
    });
    
    var toUpdate = _.filter(subscribers, function(sub){
        if (sub.var.indexOf(key + '_') === 0) return true;
        if (options.indexOf(sub.var) > -1) return true;
        return false;
    });
    

    因此,使用indexof检查字符串是否有子级。并且用父元素构建一个数组,这样任何层都是匹配的,并且在上面做一个索引。我认为这是实现它的最简单的方法