将嵌套数组转换为对象
Convert nested array into object
我所说的API在一个非常奇怪的嵌套数组结构中返回其注册表。我想把这个怪物转换成一个对象,这样我的应用程序就可以很容易地访问存储在这个输出中的整个对象。
API给我的输出是这样的:
[
[ "settings", "autoLogout", "false" ],
[ "settings", "autoLogoutMinutes", "60" ],
[ "settings", "presets", "true" ],
[ "controller", "rs232", "ip", "192.168.1.11" ],
[ "controller", "rs232", "name", "NX-22" ],
[ "source", "M23836", "slot1", "ip", "192.168.1.30" ]
]
每个数组中的最后一个值表示条目的值,最后一个之前的所有值加起来就是用于保存该值的键。由于大小限制,我不能直接将json编码的大对象放在那里,所以这不是一个可行的解决方法。
我现在已经制作了一个相当肮脏和缓慢的解决方案,涉及2个eval()。(我知道……这是否定的,所以我正在寻找更好的解决方案)我猜这可以更快地完成,但我不知道如何。。。
下面的代码段使用angular,因为我的应用程序是基于angular的,但我对任何快速/干净的解决方案都持开放态度。香草js方法或巧妙地使用lodash或下划线将非常受欢迎。
我的脏而慢的解决方案现在
function DemoCtrl($scope){
$scope.data = [
[ "settings", "autoLogout", "false" ],
[ "settings", "autoLogoutMinutes", "60" ],
[ "settings", "presets", "true" ],
[ "controller", "rs232", "ip", "192.168.1.11" ],
[ "controller", "rs232", "name", "NX-22" ],
[ "source", "M23836", "slot1", "ip", "192.168.1.30" ]
]
$scope.init = function(){
var registry = {};
angular.forEach($scope.data, function(entry){
var keys = '';
entry.forEach(function(value, key, entry){
if( key != entry.length - 1 ){
//not last of array, so must be a key
keys += '[''' + value + ''']';
// check if the object already exists
if( !angular.isDefined( eval('registry' + keys) ) ){
eval('registry' + keys + ' = {}');
}
}else{
//last one in this entry, must be the value
eval('registry' + keys + ' = ''' + value + '''');
}
});
});
console.log('registry final');
console.log(registry);
$scope.registry = registry;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app>
<div ng-controller="DemoCtrl" ng-init="init()">
<pre>{{ registry | json }}</pre>
</div>
</div>
这里有一个适合您需求的解决方案。此外,请永远不要使用eval。JavaScript总是有更好的方法。
您可以根据您的用例调整下面的代码。
var data = [
[ "settings", "autoLogout", "false" ],
[ "settings", "autoLogoutMinutes", "60" ],
[ "settings", "presets", "true" ],
[ "controller", "rs232", "ip", "192.168.1.11" ],
[ "controller", "rs232", "name", "NX-22" ],
[ "source", "M23836", "slot1", "ip", "192.168.1.30" ]
];
var o = {};
data.forEach(function(a) {
var keys = a.slice(0, a.length-2);
var cur = o;
keys.forEach(function(k) {
if (cur[k] == null) {
cur[k] = {};
}
cur = cur[k];
});
cur[a[a.length-2]] = a[a.length-1]
});
output.innerHTML = JSON.stringify(o, null, 2);
<pre id='output'></pre>
一个紧凑的解决方案,可以避免计算数组中的值位置。
var array = [
["settings", "autoLogout", "false"],
["settings", "autoLogoutMinutes", "60"],
["settings", "presets", "true"],
["controller", "rs232", "ip", "192.168.1.11"],
["controller", "rs232", "name", "NX-22"],
["source", "M23836", "slot1", "ip", "192.168.1.30"]
],
obj = {};
array.forEach(function (a) {
var p = obj,
v = a.pop(),
k = a.reduce(function (r, b) {
p[r] = p[r] || {};
p = p[r];
return b;
});
p[k] = v;
});
document.write('<pre>' + JSON.stringify(obj, 0, 4) + '</pre>');
基本上,您只需要在它们上进行循环并创建嵌套对象。您不需要为此使用eval。不应该使用它的原因有很多。性能、安全性、可调试性(https://www.nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misunderstood/)
var asObject = {}
//loop over them
data.forEach(function(val) {
//create the top level object that matches the key if it doesn't exist
if (!asObject.hasOwnProperty(val[0])) {
asObject[val[0]] = {};
}
//store it
var theHolder = asObject[val[0]];
//loop over all the middle elements creating nested object
for (var index = 1; index < val.length - 2; index++) {
var element = val[index];
if (!theHolder.hasOwnProperty[element]) {
theHolder[element] = {};
}
theHolder = theHolder[element]
}
//the last one is the value, so just set it
var lastKey = val[val.length - 2];
theHolder[lastKey] = val[val.length - 1];
});
console.log(asObject);
var someObj = $scope.data.reduce(function(accum, array) {
var value = array.pop(); //pulls last item off of array
//takes the remaining items and condenses them into 1 string
var key = array.reduce(function(acc, str) {
return acc + str;
}, '');
accum[key] = value;
return accum;
}, {}); //the empty object in this line is the seed value
每个子数组都得到处理,并传递到空的对象种子中,然后将其分配给someObj
。
function DemoCtrl($scope){
$scope.data = [
[ "settings", "autoLogout", "false" ],
[ "settings", "autoLogoutMinutes", "60" ],
[ "settings", "presets", "true" ],
[ "controller", "rs232", "ip", "192.168.1.11" ],
[ "controller", "rs232", "name", "NX-22" ],
[ "source", "M23836", "slot1", "ip", "192.168.1.30" ]
]
$scope.init = function(){
var registry = {};
angular.forEach($scope.data, function(entry) {
var len = entry.length, tmp = registry;
for (var i = 0; i < len - 1; i++) {
key = entry[i];
if (i < len - 2) {
if (!tmp[key]) {
tmp[key] = { };
}
tmp = tmp[key];
} else {
tmp[key] = entry[i + 1];
}
}
});
console.log('registry final');
$scope.registry = registry;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app>
<div ng-controller="DemoCtrl" ng-init="init()">
{{ registry }}
</div>
</div>
这里使用递归完成:
$scope.registry = $scope.data.reduce(function register(registry, entry) {
var key = entry[0];
if (entry.length === 2) {
registry[key] = entry[1];
} else {
registry[key] = register(registry[key] || {}, entry.slice(1));
}
return registry;
}, {});
这是基于@Jared Smith上述解决方案的另一个选项。在他的解决方案中,键被连接成浅映射中的字符串键。这创建了我的另一个解决方案的嵌套对象结构。
如果您是array.reduce()的新手,请参阅https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
var someObj = array.reduce(function(previousVal, currentVal) {
//strip off the value to use at the end
var value = currentVal.pop();
//create all the nested objects
currentVal.reduce(function(acc, str, idx, arr) {
if (idx !== arr.length - 1 ) {
if (!acc.hasOwnProperty(str)) {
acc[str] = {};
}
return acc[str];
} else {
//the last one in the array is the key for the value
acc[str] = value;
return;
}
}, previousVal);
return previousVal;
}, {});
console.log(someObj);
- 如何在Javascript中将JSon对象转换为数组
- 如何将TypeScript对象转换为普通对象
- JavaScript代码问题:我正在将对象转换为数组
- 如何将对象转换为数组
- JS-如何将图像对象转换为灰度并显示
- 如何将javascript对象转换为json
- 将Java对象转换为JSON
- Undercore将对象转换为数组并按关键字名称排序
- Javascript,简化了对象转换
- Mongo-JS-如何将BSON/JSON对象转换为XML
- 将一个对象转换为一个单键对象数组(带下划线?)
- 如何将一个对象转换为数组对象
- 如何将对象转换为对象数组javascript
- 将 JSON 对象转换为 JSON 树
- 将主干集合对象转换为其原始类型
- 将 JSON 对象转换为序列化字符串以进行服务器端处理
- 将 JavaScript 对象转换为其他格式
- Angularjs:将对象转换为数组
- 如何将数组的对象转换为对象
- JavaScript 中的对象转换