[英]Pluck specific javascript value from an object based on an array of indexes
给定这样的嵌套对象:
var cars = {
"bentley": {
"suppliers": [
{
"location": "England",
"name": "Sheffield Mines"}
]
// ...
}
};
像这样的数组["bentley", "suppliers", "0", "name"]
,是否存在一个将pluck_innards(cars, ['bentley', "suppliers", "0", "name"])
最深元素的现有函数,即pluck_innards(cars, ['bentley', "suppliers", "0", "name"])
并返回“ Sheffield Mines”。
换句话说,有一个函数(我将其命名为deep_pluck
),其中
deep_pluck(cars, ['bentley', 'suppliers', '0', 'name'])
=== cars['bentley']['suppliers']['0']['name']
在我看来,这很简单,但已足够普遍,以至于可以在诸如jQuery或lo-dash / underscore之类的Javascript实用程序库中完成-但我没有看到它。
我的想法很琐碎,大致如下:
function deep_pluck(array, identities) {
var this_id = identities.shift();
if (identities.length > 0) {
return deep_pluck(array[this_id], identities);
}
return array[this_id];
}
我已经在jsFiddle上发布了 。
如果函数足够智能以识别何时需要数组中的数字索引,那当然会有所帮助。 我不确定还有什么需要注意的地方。
对于我认为已经巧妙解决的问题,这是一个相当长的问题,但是我想将其发布,因为我很想看看那里有什么解决方案。
我不认为如果将数字作为0
传递给数组索引,就不会有问题。
这是没有递归的函数的替代版本:
function deep_pluck(object, identities) {
var result = object;
for(var i = 0; i < identities.length; i++) {
result = result[identities[i]];
}
return result;
}
此处的工作示例: http : //jsfiddle.net/AmH2w/1/
尽管不是通用库,但CasperJS的utils.getPropertyPath
函数似乎具有这种类型的东西。
/**
* Retrieves the value of an Object foreign property using a dot-separated
* path string.
*
* Beware, this function doesn't handle object key names containing a dot.
*
* @param Object obj The source object
* @param String path Dot separated path, eg. "x.y.z"
*/
function getPropertyPath(obj, path) {
if (!isObject(obj) || !isString(path)) {
return undefined;
}
var value = obj;
path.split('.').forEach(function(property) {
if (typeof value === "object" && property in value) {
value = value[property];
} else {
value = undefined;
}
});
return value;
}
从那以后,我遇到了几种解决方案,包括:
我还要注意相对较新的lodash.deep
。
dotty.get(obj,pathspec)执行此操作,接受数组或点分字符串作为pathspec。
Dotty是开源的,还具有一个exist方法和一个推杆。
该方法是递归的,并且与您的想法非常相似,不同之处在于dotty包含对null / undefined对象的测试,这样它就不会为尝试访问不存在的元素而引发异常。
来自文档的dotty.get()源发布在下面:
var get = module.exports.get = function get(object, path) {
if (typeof path === "string") {
path = path.split(".");
}
if (!(path instanceof Array) || path.length === 0) {
return;
}
path = path.slice();
var key = path.shift();
if (typeof object !== "object" || object === null) {
return;
}
if (path.length === 0) {
return object[key];
}
if (path.length) {
return get(object[key], path);
}
};
这是一个使用reduce
的简短ES6实现:
function get(obj, keyPath) {
return keyPath
.split(".")
.reduce((prev, curr) => prev[curr], obj);
}
用法:
get(cars, "bentley.suppliers.0.name") // -> "Sheffield Mines"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.