简体   繁体   English

通过数组中的属性查找对象

[英]Find object by properties from array

With an array, a value, and and an object with nested objects: 有一个数组,一个值和一个带有嵌套对象的对象:

Object 宾语

mesh

Array 数组

['options', 'range', 'x']

Value

12.5

Is it possible to translate this to update a property, eg 是否可以翻译此属性以更新属性,例如

mesh.options.range.x = 12.5

Attempted: 尝试:

index = (obj, i) ->
   obj[i]

arr.reduce(index, obj) = 12.5

Update 更新资料

Thank you all for the elegant solutions. 谢谢大家的优雅解决方案。

Using .reduce() is actually pretty nice for this: 实际上,使用.reduce()很不错:

// current object----|    |----current key
//                   v    v
arr.reduce(function(obj, key) {
    return obj == null ? obj : obj[key];
}, window.mesh);
//        ^
//        |-- initial object

Your attempt to use .reduce() needed to pass a function that manages the "accumulation". 您尝试使用.reduce()需要传递一个用于管理“累加”的函数。

Here, as long as the previous obj wasn't null or undefined , it'll return the key of the current obj , which becomes the next obj . 在这里,只要前一个obj不为nullundefined ,它将返回当前objkey ,该key成为下一个obj


Then since you need to assign a value, you'd actually want to get the value of the second to last key. 然后,由于您需要分配一个值,因此您实际上要获取倒数第二个键的值。

var o = arr.slice(0,-1).reduce(function(obj, key) {
    return obj == null ? obj : obj[key];
}, window.mesh);

And then check its existence and use the last item in arr to do the assignment. 然后检查其存在并使用arr的最后一项进行分配。

o && o[arr.pop()] = 12.5;

All of this can be abstracted away into a function that does one or the other based on how many arguments were passed. 所有这些都可以抽象为一个函数,该函数根据传递的参数数量来执行一个或另一个函数。

function setFromArray(obj, arr, val) {
    var keys = arguments.length < 3 ? arr.slice() : arr.slice(0, -1);

    var o = keys.slice(0,-1).reduce(function(obj, key) {
        return obj == null ? obj : obj[key];
    }, window.mesh);

    if (arguments.length < 3)
        return o;
    else 
        o && o[keys.pop()];
}

Here's a general solution: 这是一个常规解决方案:

function setPropertyPath(obj, path, value) {
    var o = obj;
    for (var i = 0; i < path.length - 1; i++) {
        o = o[path[i]];
    }
    o[path[path.length - 1]] = value;
}

Usage: 用法:

var obj = { a: { b: { c: 0 } } };
setPropertyPath(obj, ['a', 'b', 'c'], 10);
console.log(obj.a.b.c); // prints '10'

JSBin 联合会

var mesh = {},
    arr = ['options','range','x'],
    value = 12.5;

mesh[arr[0]][arr[1]][arr[2]] = value;

If array length is static do something like this: 如果数组长度是静态的,请执行以下操作:

mesh[array[0]][array[1]][array[2]] = value;

However, one problem with this is that javascript doesn't do autovivification, so if you're accessing a key value that isn't previously defined you could run into errors (if mesh.options hasn't been defined then the above will throw an error because you can't assign to it). 但是,与此相关的一个问题是javascript无法自动进行生存,因此,如果您访问的是先前未定义的键值,则可能会遇到错误(如果未定义mesh.options,则以上内容将抛出错误错误,因为您无法分配给它。 To solve that you might abstract this out into a function that handles things recursively: 为了解决这个问题,您可以将其抽象为一个递归处理函数的函数:

http://jsfiddle.net/h4jVg/ http://jsfiddle.net/h4jVg/

function update_val(obj, array, val, prev) {
    if (array.length == 0) {
        obj = val;
        return;
    }

    var cur = array.shift();

    if(array.length == 0) {
        obj[cur] = val;
        return;
    } else if (obj[cur] == undefined) {
        obj[cur] = {};
    }

    update_val(obj[cur], array, val);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM