I am looking for a HashMap sort of implementation in Javascript for JSON for the following case.
I have the JSON with following structure:
{
"level1": {
"level2": [{
"product1": [
"item1",
"item2"
]
}, {
"product2": [
"item1",
"item2"
]
}, {
"product3": [
"item5",
"item6"
]
}]
}
}
For my use case, I get a value , say 'product3', I want to find values for this key ie "item5", "item6". I have a way, that i can loop through the entire level2 object but want to know if I can simply use key to find values.
You can build yourself either an object or (in ES2015) a Map
:
Here's an ES5 example using an object:
var map = Object.create(null);
data.level1.level2.forEach(function(entry) {
Object.keys(entry).forEach(function(key) {
map[key] = entry;
});
});
Live example:
var data = { "level1": { "level2": [{ "product1": [ "item1", "item2" ] }, { "product2": [ "item1", "item2" ] }, { "product3": [ "item5", "item6" ] }] } }; var map = Object.create(null); data.level1.level2.forEach(function(entry) { Object.keys(entry).forEach(function(key) { map[key] = entry; }); }); var name = "product2"; console.log(map[name]);
We create the object ( map
) using Object.create(null)
so that it doesn't have a prototype, and so doesn't have the pre-existing inherited properties like toString
and valueOf
.
The inner loop, on the result of Object.keys
, is necessary because each object in the level2
array has a different name for its only property. That's an unusual and a bit awkward structure.
In ES2015 (aka "ES6") with Map
, it's very similar you just use new Map
and set
:
var map = new Map();
data.level1.level2.forEach(function(entry) {
Object.keys(entry).forEach(function(key) {
map.set(key, entry);
});
});
Live example:
var data = { "level1": { "level2": [{ "product1": [ "item1", "item2" ] }, { "product2": [ "item1", "item2" ] }, { "product3": [ "item5", "item6" ] }] } }; var map = new Map(); data.level1.level2.forEach(function(entry) { Object.keys(entry).forEach(function(key) { map.set(key, entry); }); }); var name = "product2"; console.log(map.get(name));
"One-line" optimized solution using Array.some
, Array.indexOf
and Object.keys
functions (no need to iterate through all "product" objects):
// json is your initial object
var key = 'product3', values;
json['level1']['level2'].some((v) => Object.keys(v).indexOf(key) !== -1 && (values = v[key]), values);
console.log(values); // ["item5", "item6"]
Explanation :
arr.some(callback[, thisArg])
- This function returns true if the callback function returns a truthy value for any array element; In my example values
becomes thisArg
parameter which should contain values of the desired "keyName".
It will iterate through all "product" objects, but will stop looping immediately if the required keyName is found amoung the properties of the current object ( Object.keys(v).indexOf(key) !== -1
).
As a concurrent condition it should save the values of found object which can be achieved with truthy assignment expression && (values = v[key])
.
That's all.
You could just transform data to different structure.
const data = { "level1": { "level2": [{ "product1": [ "item1", "item2" ] }, { "product2": [ "item3", "item4" ] }, { "product3": [ "item5", "item6" ] }] }, "level1b": { "level2": [{ "product1": [ "item1b", "item2" ] }, { "product2": [ "item3", "item4" ] }, { "product3": [ "item5", "item6" ] }] } }; const transformed = Object .keys(data) .reduce((obj, key) => { const value = data[key]; return Object.assign(obj, {[key]: transformLvl2(value)}); }, {}); console.log(transformed.level1.level2.product2); console.log(transformed.level1.level2.product1); console.log(transformed.level1.level2.product3); console.log(transformed.level1b.level2.product1); function transformLvl2(level2) { return Object .keys(level2) .reduce((obj, key) => { const value = level2[key]; return Object.assign(obj, {[key]: transformLvl3(value)}); }, {}); } function transformLvl3(level3) { return level3 .reduce((obj, value) => { return Object.assign(obj, value); }, {}); }
try (assuming that level1
and level2
is generic)
var obj = { "level1": { "level2": [{ "product1": [ "item1", "item2" ] }, { "product2": [ "item1", "item2" ] }, { "product3": [ "item5", "item6" ] }] } }; var keyName = "product3"; var items = []; Object.keys(obj).forEach(function(key) { Object.keys( obj[key] ).forEach(function(key1){ obj[key][key1].forEach(function(obj1){ Object.keys(obj1).forEach(function(key2) { if (key2 == keyName) { items = items.concat(obj1[key2]); } }); }); }); }); console.log(items);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.