Convert an Object into an Object of Objects - javascript

I have an Object:
{
"Results": {
"circle": 0.06879016757011414,
"quad": {
"exp": 0.8039023876190186,
"actual": 0.19609761238098145
},
"square": 0.8266428709030151
}
}
I want to convert it to:
{
"Results": {
"circle": {
"circle": 0.06879016757011414
},
"quad": {
"exp": 0.8039023876190186,
"actual": 0.19609761238098145
},
"square": {
"square": 0.8266428709030151
}
}
}
Have tried this code:
var modData = {};
data = data.Results;
for (var key in data) {
if (data.hasOwnProperty(key)) {
modData[key] = data[key];
for (var innerKey in data[key]) {
modData[key] = data[key];
}
}
}
console.log("Modified is:", modData);
Unfortunately, this still returns the original object, what is it that I am doing which is wrong?
A jquery solution is fine as well.

Loop trough the properties with for .. in and any property is not an object replace it with one. Like this:
let x = {
"Results": {
"circle": 0.06879016757011414,
"quad": {
"exp": 0.8039023876190186,
"actual": 0.19609761238098145
},
"square": 0.8266428709030151
}
}
for (key in x.Results) {
if (typeof x.Results[key] !== 'object')
x.Results[key] = {
[key]: x.Results[key]
}
}
console.log(x);
If you want to preserve the original object do this:
let data = {
"Results": {
"circle": 0.06879016757011414,
"quad": {
"exp": 0.8039023876190186,
"actual": 0.19609761238098145
},
"square": 0.8266428709030151
}
}
data = data.Results;
modData = {};
for (key in data) {
if (typeof data[key] !== 'object')
modData[key] = { [key]: data[key] }
else
modData[key] = { [key]: data[key] }
}
console.log(modData);

You could check the type and if not an object then assign a new object with the same key and value.
This proposal uses computed property names for getting a variable as key for an object.
var object = { Results: { circle: 0.06879016757011414, quad: { exp: 0.8039023876190186, actual: 0.19609761238098145 }, square: 0.8266428709030151 } };
Object
.keys(object.Results)
.forEach(function (k) {
if (object.Results[k] && typeof object.Results[k] !== 'object') {
object.Results[k] = { [k]: object.Results[k] };
}
});
console.log(object);
.as-console-wrapper { max-height: 100% !important; top: 0; }

The value that should be stored in modData should be the object itself rather than the value. This code gives the expected value
var modData = {};
data = data.Results;
for (var key in data) {
if (data.hasOwnProperty(key)) {
var temp = Object();
temp[key] = data[key];
modData[key] = temp;
for (var innerKey in data[key]) {
var temp = Object();
temp[key] = data[key];
modData[key] = temp;
}
}
}

const input = {
"Results": {
"circle": 0.06879016757011414,
"quad": {
"exp": 0.8039023876190186,
"actual": 0.19609761238098145
},
"square": 0.8266428709030151
}
};
const result = {
Results: {}
};
//If you want object construct specifically for "circle" & "square"
for (let key in input.Results) {
if (input.Results.hasOwnProperty(key)) {
if (key === 'circle') {
result.Results.circle = {
'circle': input.Results[key]
}
} else if (key === 'square') {
result.Results.square = {
'square': input.Results[key]
}
} else {
result.Results[key] = input.Results[key];
}
}
}
//Generically construct object if key is not object
for (let key in input.Results) {
if (input.Results.hasOwnProperty(key)) {
if (key !== 'object') {
result.Results[key] = {
[key]: input.Results[key]
}
}
}
}
console.log(result);

Related

Get path to JSON object by key?

Given the following object:
const ourObject = {
"payload": {
"streams": [
{
"children": {
"2165d20a-6276-468f-a02f-1abd65cad618": {
"additionalInformation": {
"narrative": {
"apple": "A",
"banana": "B"
},
"myInventory": {
"fruits": [
{
"name": "apple"
},
{
"name": "banana"
}
]
}
}
}
}
}
]
}
};
We're trying to find the path of myInventory, the issue is that the children's uuid will be different each time. Any idea how we can get the path to myInventory by providing it as a key and get the json path to it?
If things are dynamic, a programmatic key search could help
const ourObject = {
"payload": {
"streams": [
{
"children": {
"2165d20a-6276-468f-a02f-1abd65cad618": {
"additionalInformation": {
"narrative": {
"apple": "A",
"banana": "B"
},
"myInventory": {
"fruits": [
{
"name": "apple"
},
{
"name": "banana"
}
]
}
}
}
}
}
]
}
};
const getPath = (key, o) => {
if (!o || typeof o !== "object") {
return "";
}
const keys = Object.keys(o);
for(let i = 0; i < keys.length; i++) {
if (keys[i] === key ) {
return key;
}
const path = getPath(key, o[keys[i]]);
if (path) {
return keys[i] + "." + path;
}
}
return "";
};
const getValueForKey = (key, o) => {
if (!o || typeof o !== "object") {
return undefined;
}
const keys = Object.keys(o);
for(let i = 0; i < keys.length; i++) {
if (keys[i] === key ) {
return o[key];
}
const value = getValueForKey(key, o[keys[i]]);
if (value) {
return value;
}
}
return undefined;
}
console.log(getPath("myInventory", ourObject))
console.log(getValueForKey("myInventory", ourObject))
Not sure if I understand the question right but
let uuid = '2165d20a-6276-468f-a02f-1abd65cad618';
ourObject.payload.streams[0].children[uuid].additionalInformation.myInventory
var changingKey = Object.keys(ourObject["payload"]["streams"][0]["children"])[0];
console.log(ourObject["payload"]["streams"][0]["children"][changingKey]["additionalInformation"]["myInventory"]);
Okay, you could create a helper function that gets the UUID. Since it's an object, the lookup is close to O(1) especially given the case that the children has only one key-value pair here.
function getUUIDFromPayload(payload) {
let obj = payload.streams[0].children
let uuid = Object.keys(obj)[0]
return uuid
}
Usage
const uuid = getUUIDFromPayload(payload)
ourObject.payload.streams[0].children[uuid].additionalInformation.myInventory

Searching the entire JSON tree based on keys at every level

I am trying to Search in a tree, but my results are not as expected. Can any body please help?
function treeSearch(searchedValue,ExceptionTree:){
let result = {};
var childrenKeys = Object.keys(ExceptionTree);
for(let i = 0; i< childrenKeys.length;i++){
if(childrenKeys[i].toLowerCase().indexOf(searchedValue) >=0 || Object.keys( treeSearch( ExceptionTree[childrenKeys[i]] , searchedValue ) ).length >=0 )
result[childrenKeys[i]] = ExceptionTree[childrenKeys[i]];
}
return result;
}
Below is the sample Input:
var myTree= {
"North America": {
"Canada": {
"VanCouver": 1,
"Ottawa": 2
},
"US": {
"Florida": 3,
"Texas": 4
}
},
"Asia": {
"India": {
"Mumbai": 5,
"Delhi": 6
},
"China": {
"Shanghai": 9,
"Beijing": 10
}
}
}
If I call
treeSearch("Texas",myTree)
the result should be
{
"North America": {
"USA": {
"Texas":4
}
}
}
I am either getting the entire tree returned or an empty tree. Any suggestions?
Try this (details in comments):
// Insert your tree and text to find
function treeSearch(tree, text) {
let result = null;
// Loop input tree
for (const [key, value] of Object.entries(tree)) {
if (typeof(value) === "object") {
// Recursive call on an sub-objects
const found = treeSearch(value, text);
if (found) {
result = { [key]: found };
}
} else if (key === text) {
// Result found
result = { [key]: value };
}
}
return result;
}
const result = treeSearch(myTree, "Texas");
Result is an object below or null if text wasn't found
{
North America: {
US: {
Texas: 4
}
}
}
Here is an iterative solution using object-scan
// const objectScan = require('object-scan');
const myTree = { 'North America': { Canada: { VanCouver: 1, Ottawa: 2 }, US: { Florida: 3, Texas: 4 } }, Asia: { India: { Mumbai: 5, Delhi: 6 }, China: { Shanghai: 9, Beijing: 10 } } };
const treeSearch = (name, tree) => objectScan(['*.*.*'], {
abort: true,
filterFn: ({ property, key, value, context }) => {
if (property !== name) {
return false;
}
key.reduce((p, c, idx) => {
p[c] = idx === key.length - 1 ? value : {};
return p[c];
}, context);
return true;
}
})(tree, {});
console.log(treeSearch('Texas', myTree));
// => { 'North America': { US: { Texas: 4 } } }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan#13.8.0"></script>
Disclaimer: I'm the author of object-scan

How to merge two objects of all properties in an array if it has same id in javascript?

JSON: (I have two same object properties in array. i would like merge all the property values of this array. I have added other case, if id gets changed, it should give like below. )
const array = [{
Lot_id:{
id:1,
qty_receive:30,
qty_return:5,
qty_remain:15
},
qty_allocate:10,
remaining_qty:20
},
{
Lot_id:{
id:1,
qty_receive:30,
qty_return:5,
qty_remain:15
},
qty_allocate:10,
remaining_qty:20
},
{
Lot_id:{
id:2,
qty_receive:30,
qty_return:5,
qty_remain:15
},
qty_allocate:10,
remaining_qty:20
}]
expected result:(updated my question)
const array = [{
Lot_id:{
id:1,
qty_receive:60,
qty_return:10,
qty_remain:30
}
qty_allocate:20,
remaining_qty:40
},
{
Lot_id:{
id:2,
qty_receive:30,
qty_return:5,
qty_remain:15
},
qty_allocate:10,
remaining_qty:20
}]
Can u try this?
const array = [
{ Lot_id:{ id:1, qty_receive:30, qty_return:5, qty_remain:15}, qty_allocate:10},
{ Lot_id:{ id:1, qty_receive:30, qty_return:5, qty_remain:15}, qty_allocate:10},
{ Lot_id:{ id:2, qty_receive:30, qty_return:5, qty_remain:15}, qty_allocate:10},
]
function merge(array){
var result = [];
array.reduce(function(res, value) {
if (!res[value.Lot_id.id]) {
res[value.Lot_id.id] = {
Lot_id: {
id:value.Lot_id.id,
qty_receive:0,
qty_return:0,
qty_remain:0,
}, qty_allocate: 0
};
result.push(res[value.Lot_id.id])
}
res[value.Lot_id.id].qty_allocate += value.qty_allocate;
res[value.Lot_id.id].Lot_id.qty_receive += value.Lot_id.qty_receive;
res[value.Lot_id.id].Lot_id.qty_return += value.Lot_id.qty_return;
res[value.Lot_id.id].Lot_id.qty_remain += value.Lot_id.qty_remain;
return res;
}, {});
return result
}
console.log(merge(array));
const reduceArr = array.reduce((total, {Lot_id: {qty_receive, qty_return, qty_remain}, qty_allocate}) => {
total.Lot_id.qty_receive += qty_receive;
total.Lot_id.qty_return += qty_return;
total.Lot_id.qty_remain += qty_remain;
total.qty_allocate += qty_allocate;
return [total];
});
Update answer according to your updated question:
const mergeArr = () => {
const newArr = [];
let tempId = 0;
array.forEach((item, index) => {
if (tempId !== item.Lot_id.id) {
tempId = item.Lot_id.id;
newArr.push(item);
} else {
const lastItem = newArr[newArr.length - 1];
const lastLot = lastItem.Lot_id;
const newLot = item.Lot_id;
lastLot.qty_receive += newLot.qty_receive;
lastLot.qty_return += newLot.qty_return;
lastLot.qty_remain += newLot.qty_remain;
lastItem.remaining_qty += item.remaining_qty;
lastItem.qty_allocate += item.qty_allocate;
}
});
return newArr;
}
console.log(mergeArr());
try the code here:
https://repl.it/repls/SparseUnfortunateLanguage
Try this instead,
let result = mergeElements(array);
console.log(result);
/**
* function accepts the array of objects you need to merge by adding fields
* */
function mergeElements(array = []) {
let sumOf = [];
if (array.length <= 1) {
return array;
} else {
sumOf[0] = array[0];
let index = 0;
array.forEach(function (item, index) {
if (index != 0) {
sumOf[0] = iterateItem(item, sumOf[0]);
}
index++;
});
}
return sumOf;
}
/**
*function for indepth iteration of objects
* */
function iterateItem(item, sumOf) {
if (typeof item == "object") {
for (let key in item) {
if (typeof item[key] != "object") {
if (typeof sumOf[key] == "undefined") {
sumOf[key] = 0;
}
if (key == "id") {
continue;
}
sumOf[key] += item[key];
} else {
if (typeof sumOf[key] == "undefined") {
sumOf[key] = {};
}
sumOf[key] = iterateItem(item[key], sumOf[key]);
}
}
} else {
sumOf += item;
}
return sumOf;
}
I hope this will help you to solve your problem.
You can check my solution for your issue.
const array = [
{
Lot_id: {
id: 1,
qty_receive: 30,
qty_return: 5,
qty_remain: 15,
},
qty_allocate: 10,
},
{
Lot_id: {
id: 1,
qty_receive: 30,
qty_return: 5,
qty_remain: 15,
},
qty_allocate: 10,
},
{
another_id: {
id: 1,
qty_receive: 30,
qty_return: 5,
qty_remain: 15,
},
qty_allocate: 10,
},
{
another_id: {
id: 1,
qty_receive: 30,
qty_return: 5,
qty_remain: 15,
},
qty_allocate: 10,
},
];
const isObject = (value) => {
return (
typeof value === "object" &&
value instanceof Object &&
!(value instanceof Array)
);
};
const result = array.reduce((acc, obj) => {
const existingObj = acc.find((accObj) => {
return Object.keys(accObj).every(
(key) => Object.keys(obj).indexOf(key) > -1
);
});
if (existingObj) {
Object.keys(obj).forEach((key) => {
if (isObject(obj[key])) {
const innerObj = obj[key];
const existingInnerObj = existingObj[key];
Object.keys(innerObj).forEach((innerKey) => {
if(innerKey !== 'id') {
existingInnerObj[innerKey] += innerObj[innerKey];
}
});
} else {
existingObj[key] += obj[key];
}
});
} else {
acc.push(obj);
}
return acc;
}, []);
console.log(result);

How to convert multiple dimension list into one dimension list

If I have this JSON data that is from the original file.
[{"food": {"spicy": "spicy","sweet": "sweet"},
"water": {"sweet": "sweet","sour": {"cold": "ice lemon","hot": "lemon tea"}}
}, {"food": {"spicy": "spicy","sweet": "sweet"},
"water": {"sweet": "sweet","sour": {"cold": "ice lemon","hot": "lemon tea"}}
}]
how do I convert into a one-dimensional list like this?
[{
"food-spicy": "spicy",
"food-sweet ": "sweet",
"water-sweet ": "sweet",
"water-sour-cold ": "ice lemon",
"water-sour-hot ": "lemon tea"
}, {
"food-spicy": "spicy",
"food-sweet ": "sweet",
"water-sweet ": "sweet",
"water-sour-cold ": "ice lemon",
"water-sour-hot ": "lemon tea"
}]
Please help.
You could write a function that flatten an object recursively. Then map the array using that function:
function flatten(oldObj) {
return Object.keys(oldObj).reduce(function(newObj, oldKey) { // for each key "oldKey" in oldObj
var value = oldObj[oldKey]; // get the value of the current oldKey from oldObj
if(value && typeof(value) === "object") { // if the value is also an object (add "&& !Array.isArray(value)" to exclude arrays)
value = flatten(value); // then flatten it first
Object.keys(value).forEach(function(key) { // and for each key in the new flattened value object
newObj[oldKey + "-" + key] = value[key]; // add a key-value to newObj where key is "oldKey-key" and the value is value[key]
});
} else {
newObj[oldKey] = value; // otherwise (if the value is not an object), just copy the key-value to newObj as it is
}
return newObj;
}, {});
}
Then use it like this:
var newArray = oldArray.map(flatten);
Example:
function flatten(oldObj) {
return Object.keys(oldObj).reduce(function(newObj, oldKey) {
var value = oldObj[oldKey];
if(value && typeof(value) === "object") {
value = flatten(value);
Object.keys(value).forEach(function(key) {
newObj[oldKey + "-" + key] = value[key];
});
} else {
newObj[oldKey] = value;
}
return newObj;
}, {});
}
var oldArray = [{"food":{"spicy":"spicy","sweet":"sweet"},"water":{"sweet":"sweet","sour":{"cold":"ice lemon","hot":"lemon tea"}}},{"food":{"spicy":"spicy","sweet":"sweet"},"water":{"sweet":"sweet","sour":{"cold":"ice lemon","hot":"lemon tea"}}}];
var newArray = oldArray.map(flatten);
console.log(newArray);
try this:
var data = [{
food: {
spicy: 'spicy',
sweet: 'sweet'
},
water: {
sweet: 'sweet',
sour: {
cold: 'ice lemon',
hot: 'lemon tea'
}
}
},
{
food: {
spicy: 'spicy',
sweet: 'sweet'
},
water: {
sweet: 'sweet',
sour: {
cold: 'ice lemon',
hot: 'lemon tea'
}
}
}
]
var res = data.map(obj => {
return Reflect.ownKeys(obj).reduce((re, key) => {
Reflect.ownKeys(obj[key]).reduce((r, k) => {
if (typeof obj[key][k] === 'object') {
Reflect.ownKeys(obj[key][k]).reduce((r2, k2) => {
r2[key + '-' + k + '-' + k2] = obj[key][k][k2]
return r2
}, r)
} else {
r[key + '-' + k] = obj[key][k]
return r
}
}, re)
return re
}, {})
})
console.log(res)
And here is a more universal version which applicable for more nested obj
var data = [{
food: {
spicy: 'spicy',
sweet: 'sweet'
},
water: {
sweet: 'sweet',
sour: {
cold: 'ice lemon',
hot: 'lemon tea'
}
}
},
{
food: {
spicy: 'spicy',
sweet: 'sweet'
},
water: {
sweet: 'sweet',
sour: {
cold: 'ice lemon',
hot: 'lemon tea'
}
}
}
]
function customReduce(obj, subObj, lastReduceObj = {}, lastKey = '') {
let res = Reflect.ownKeys(subObj).reduce((re, key) => {
if (lastKey === '') {
customReduce(obj, obj[key], re, key)
} else if (typeof subObj[key] === 'object') {
customReduce(obj, subObj[key], re, lastKey + '-' + key)
} else {
re[lastKey + '-' + key] = subObj[key]
}
return re
}, lastReduceObj)
return res
}
var res = data.map(obj => {
return customReduce(obj, obj)
})
console.log(res)
Try this :
var jsonObj = [{
"food": {
"spicy": "spicy",
"sweet": "sweet"
},
"water": {
"sweet": "sweet",
"sour": {
"cold": "ice lemon",
"hot": "lemon tea"
}
}
}, {
"food": {
"spicy": "spicy",
"sweet": "sweet"
},
"water": {
"sweet": "sweet",
"sour": {
"cold": "ice lemon",
"hot": "lemon tea"
}
}
}];
var newObj = {};
for (var i in jsonObj) {
for (var j in Object.keys(jsonObj[i])) {
for (var k in Object.keys(jsonObj[i])[j]) {
newObj[Object.keys(jsonObj[i])[j]+'-'+Object.keys(jsonObj[i][Object.keys(jsonObj[i])[j]])[k]] = jsonObj[i][Object.keys(jsonObj[i])[j]][Object.keys(jsonObj[i][Object.keys(jsonObj[i])[j]])[k]];
}
}
}
console.log([flatJSON(newObj)]);
function flatJSON(obj) {
if(typeof obj != 'object') {
return;
}
for (var l in Object.keys(obj)) {
if (typeof obj[Object.keys(obj)[l]] == 'object') {
for (var m in Object.keys(obj[Object.keys(obj)[l]])) {
newObj[Object.keys(obj)[l]+'-'+Object.keys(obj[Object.keys(obj)[l]])[m]] = obj[Object.keys(obj)[l]][Object.keys(obj[Object.keys(obj)[l]])[m]];
}
}
if (typeof obj[Object.keys(obj)[l]] == 'object') {
delete obj[Object.keys(obj)[l]];
}
if (obj[Object.keys(obj)[l]] === undefined) {
delete obj[Object.keys(obj)[l]];
}
}
return newObj;
}

How to flatten a nested JSON data structure into an object with key value pairs

The strings that are coming from source is coming in fragmented JSON object in JSON object.I want to convert this JSON structure to flat JSON structure
{
"nest": {
"a": {
"b": {
"h": {
"i": {
"all.css": "1",
"j": {
"k": {
"l": {
"lr.png": "2",
"c.png": "3"
},
".png": "4"
}
}
}
}
}
}
}
}
I tried to do it but I could only get up to 1 key value pair,
what i want is {"abhiall.css":"1","abhijkllr.png":"2","abhijklc.png":"3" ..and so on.
Thanks
You could use an iterative and recursive approach for nested objects.
function flatten(object, target, path) {
path = path || '';
Object.keys(object).forEach(function (key) {
if (object[key] && typeof object[key] === 'object') {
flatten(object[key], target, path + key);
return;
}
target[path + key] = object[key];
});
}
var data = { nest: { a: { b: { h: { i: { "all.css": "1", j: { k: { l: { "lr.png": "2", "c.png": "3" }, ".png": "4" } } } } } } } },
flat = {};
flatten(data.nest, flat);
console.log(flat);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can user recursive function to return desired result.
var obj = {"nest":{"a":{"b":{"h":{"i":{"all.css":"1","j":{"k":{"l":{"lr.png":"2","c.png":"3"},".png":"4"}}}}}}}}
function flat(data, c) {
var result = {}
for(var i in data) {
if(typeof data[i] == 'string') result[c + i] = data[i]
if(typeof data[i] == 'object') result = Object.assign(result, flat(data[i], c+= i))
}
return result
}
console.log(flat(obj.nest, ''))
For array of objects I did the following
Note : make sure the Objects Array passed in is n>0 at least
flatten(objects, target, path) {
let me = this;
let retArray = [];
for(let x=0; x < objects.length; x++) {
let object = objects[x];
path = path || '';
target={};
target = me.flattenHelper(object, target, path);
retArray.push(target);
}
return retArray;}
..
flattenHelper(object, target, path){
let me = this;
Object.keys(object).forEach(function (key) {
console.log("key : "+ key + " : object : " + (object[key] && typeof object[key] === 'object') + " path : " + path);
if (object[key] && typeof object[key] === 'object') {
me.flattenHelper(object[key], target, path + key);
}
target[path + key] = object[key];
console.log(target);
});
return target;}
Using this function:
const flattenObject = (obj, prefix = '') =>
Object.keys(obj).reduce((acc, k) => {
const pre = prefix.length ? prefix : '';
if (typeof obj[k] === 'object') Object.assign(acc, flattenObject(obj[k], pre + k));
else acc[pre + k] = obj[k];
return acc;
}, {});
console.log(flattenObject({"nest": {"a": {"b": {"h": {"i":{"all.css":"1","j": {"k": {"l": {"lr.png": "2","c.png": "3"},".png": "4"}}}}}}}}));
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

Categories