How to get the parent object value using child value - javascript

I have value "b" with me and I want to get the item "3648" using that how can I do that using JavaScript?
{
"someID": "16385421",
"items": {
"9836": {
"id": "a"
},
"3648": {
"id": "b"
},
"7738": {
"id": "c"
}
}
}
o/p
"3648": {
"id": "b"
}

Edited after your comment:
getByItemId = ( val ) => {
let result;
for( let elem in data.items ){
const check = data.items[ elem ];
if( check.id == val ) result = check;
}
console.log( result )
return result;
}
getByItemId( "b" )

You could do it with some code that resembled the following.
First we get all of the object keys in the obj.items object.
Next we iterate through them.
At each step, we check to see if the desired ID is contained within the sub-object indexed by the current key in the array. If it's found, we update the result object.
We then return an empty object if the key isn't present, and something like the following if it was found: {key: '3648', id: 'b'}.
"use strict";
function byId(id){return document.getElementById(id)}
function qs(sel,parent=document){return parent.querySelector(sel)}
function qsa(sel,parent=document){return parent.querySelectorAll(sel)}
window.addEventListener('load', onLoaded, false);
var rawData = {
"someID": "16385421",
"items": {
"9836": {
"id": "a"
},
"3648": {
"id": "b"
},
"7738": {
"id": "c"
}
}
};
function getIDs(data, searchItemId)
{
let keys = Object.keys(data.items);
let result = {};
keys.forEach( keyFunc );
return result;
function keyFunc(elem, index, collection)
{
if (data.items[elem].id == searchItemId)
{
result.key = elem;
result.id = searchItemId;
}
}
}
function onLoaded(evt)
{
console.log( getIDs(rawData, "b") );
}

You can do:
const obj = {
someID: '16385421',
items: {
9836: {
id: 'a',
},
3648: {
id: 'b',
},
7738: {
id: 'c',
},
},
}
const getParentObjectByValue = (obj, value) => {
const key = Object.keys(obj.items).find((k) => obj.items[k].id === value)
return key ? { [key]: obj.items[key].id } : undefined
}
console.log(getParentObjectByValue(obj, 'b'))
console.log(getParentObjectByValue(obj, 'zz'))

Related

Updating the object based on the presence of the key else form a new object : Javascript

Have an object with following format:
let obj = {
p2: {
p21: [
{
key1: "val1",
value1: "val2"
},
{
prop: "test",
value: "dummy"
}
]
}
}
I basically have to see if there is an object that has key "prop" and replace with whatever the passed value. If such key does not present create an object with { "prop" : "test" , value: passed_value} and add it to the p21 array. Also this object containing key "prop" can be present anywhere inside p21 array
Should be something like this
function checkAndUpdate(replacingValue) {
if(obj's p21 has key name "prop")
{
//update its "value" to the passed "replacingValue"
}
else //if "prop" key not present
{
// create an object with { "prop": "test" , value: replacingValue} and add it to p21 array
}
}
Have tried following:
obj.p2.p21.map((elem) => {
if(Object.keys(elem)[0] === "prop")
elem.value = updateValue;
})
Use .findIndex to find the index of the matching object. If it exists, .slice the array before and after it, and in the middle, insert the updated object. Otherwise, just spread the object into the array:
let obj = {
"p2": {
"p21": [{
"key1": "val1",
"value1": "val2",
},
{
"prop": "test",
"value": "dummy"
}
]
}
}
function checkAndUpdate(value) {
const newObj = { prop: 'test', value}
const arr = obj.p2.p21;
const index = arr.findIndex(obj => obj.hasOwnProperty('prop'));
const newArr = index !== -1
? [...arr.slice(0, index), newObj, ...arr.slice(index + 1)]
: [...arr, newObj];
const fullNewObj = {
...obj,
p2: {
...obj.p2,
p21: newArr
}
};
return fullNewObj;
}
console.log(checkAndUpdate('foo'));
To also check whether the value is undefined, and remove the matching object from the array if so, just make the appropriate if checks, and slice the array as needed:
let obj = {
"p2": {
"p21": [{
"key1": "val1",
"value1": "val2",
},
{
"prop": "test",
"value": "dummy"
}
]
}
}
function checkAndUpdate(value) {
const newObj = { prop: 'test', value}
const arr = obj.p2.p21;
const index = arr.findIndex(obj => obj.hasOwnProperty('prop'));
const newArr = (() => {
if (index === -1) {
if (value === undefined) {
return arr;
}
return [...arr, newObj];
}
if (value === undefined) {
return [...arr.slice(0, index), ...arr.slice(index + 1)];
}
return [...arr.slice(0, index), newObj, ...arr.slice(index + 1)];
})();
const fullNewObj = {
...obj,
p2: {
...obj.p2,
p21: newArr
}
};
return fullNewObj;
}
console.log(checkAndUpdate('foo'));
You can use Array.find to find the object that hasOwnProperty prop and update
let obj = {
"p2": {
"p21": [{
"key1": "val1",
"value1": "val2",
},
{
"prop": "test",
"value": "dummy"
}
]
}
}
function rep(value) {
if (!value.length) {
obj.p2.p21 = [...obj.p2.p21].filter(e => e.hasOwnProperty('prop'));
return;
}
let ele = obj.p2.p21.find(e => e.hasOwnProperty('prop'));
if (ele) {
ele.value = value
return;
}
obj.p2.p21.push({
"prop": "test",
value
})
}
rep('test');
console.log(JSON.stringify(obj))
rep('');
console.log(JSON.stringify(obj))

Getting bug in recursive functions?

I am using an array with nested object of array. Assigning the values in array's values according to input line index, values are passed into the array's indexed value. I have checked the condition that if in array object is there, it converts it into array and call the recursive function and it calls recursion until the object's array's value is full but don't know why it is not working properly. Please help me in this bug
(function($) {
var xmlOutput = document.querySelector(".xmlOutput");
let templateStore = [];
let preservedEntriesValue = [];
let selectedTemplate = [];
function generateDOMDropdown(selectedID) {
let optionTemplate = templateStore.map(function(entry) {
return `<option value="${
entry.id
}" ${entry.id === selectedID ? "selected" : ""}>${entry.name}</option>`;
});
$("#select").html(optionTemplate);
}
function processEntries(entries) {
let output = "";
for (const entry of entries) {
output += entry;
}
return output;
}
function parseJSONToXML(input) {
const domStructure = input.entriesValue.map(function(tagObj) {
if (typeof tagObj === "string") {
return `<${tagObj}></${tagObj}>`;
} else if (Array.isArray(tagObj)) {
if (tagObj.length > 1) {
return `<${tagObj[0]}>${tagObj[1]}</${tagObj[0]}>`;
} else if (tagObj.length == 1) {
return `<${tagObj[0]}></${tagObj[0]}>`;
}
} else {
const outerTag = Object.keys(tagObj).pop();
const innerDOM = parseJSONToXML({ entriesValue: tagObj[outerTag] });
return `<${outerTag}>${processEntries(innerDOM)}</${outerTag}>`;
}
});
return domStructure;
}
function preFillSelected() {
const root = selectedTemplate.root;
const domStructure = parseJSONToXML(selectedTemplate);
xmlOutput.innerText = vkbeautify.xml(
`<?xml version="1.0" encoding="UTF-8"?><${root}>${processEntries(
domStructure
)}</${root}>`,
5
);
}
$.ajax({
type: "get",
url: window.location.origin + "/templates.json",
success: function(data) {
templateStore = data;
if (data.length > 0) {
selectedTemplate = data[0];
generateDOMDropdown(selectedTemplate.id);
preservedEntriesValue = selectedTemplate.entriesValue;
preFillSelected();
$("#select")
.off("change")
.on("change", function() {
selectedTemplate = templateStore[$("#select").val()];
preservedEntriesValue = selectedTemplate.entriesValue;
preFillSelected();
window.template = selectedTemplate;
});
}
}
});
function generateValueJSON(
template,
lines,
inputLen,
templateLen,
flatLen,
cidx
) {
cidx = cidx || 0;
// console.log('Entry', lines, template, cidx);
return Array.from(template.entriesValue.entries()).map(([idx, entry]) => {
console.log("Lines", lines);
if (idx < lines.length) {
if (Array.isArray(entry)) {
return [entry[0], lines[idx]];
} else if (typeof entry === "object") {
// debugger;
const outerTag = Object.keys(entry).pop();
const innerLength = entry[outerTag].length;
if (cidx === 0) cidx = idx;
const outerIdx = cidx + innerLength;
// console.log((flatLen - templateLen - inputLen));
// console.log({ flatLen, templateLen, inputLen, outerIdx, cidx, idx });
const innerObj = generateValueJSON(
{ entriesValue: entry[outerTag] },
lines.slice(idx, outerIdx),
inputLen,
templateLen,
flatLen,
idx
);
// cidx = 0;
entry[outerTag] = innerObj;
return entry;
}
return [entry, lines[idx]];
}
return entry;
});
}
function mapLength(template) {
return template.entriesValue
.map((entry) => {
return typeof entry === "object"
? [Object.keys(entry), Object.values(entry)]
: entry;
})
.flat(3).length;
}
$("#txtInput").on("keyup", function() {
const lines = $(this)
.val()
.split("\n\n")
.map((v) => v.trim().replace(/\n/g, "<br/>"));
// console.log(preservedEntriesValue);
selectedTemplate.entriesValue = preservedEntriesValue;
templateLength = mapLength(selectedTemplate);
const newEntriesValue = generateValueJSON(
selectedTemplate,
lines,
lines.length,
selectedTemplate.entriesValue.length,
templateLength
);
// console.log(newEntriesValue);
selectedTemplate.entriesValue = newEntriesValue;
preFillSelected();
});
})(window.jQuery, Node);
//here is the data array
[{
"id": "1",
"name": "Template Name 2",
"root": "media",
"entriesValue": [
"mediaid",
"category",
"provider",
"date",
"caption_photo_1",
{
"image": [
"imageid",
"type",
"width",
"hfive"
]
},
{
"video": [
"name",
"type",
"bitrate",
"size",
"width",
"hfive",
"headline",
"summary"
]
}
]
},
{
"id": "0",
"name": "Template Name 1",
"root": "article",
"entriesValue": [
"author",
"headline",
"cats",
"subcats",
"image",
"video",
"tags",
"summary",
"content"
]
},
{
"id": "2",
"name": "Template Name 3",
"root": "article",
"entriesValue": [
"author",
"headline",
"cats",
"subcats",
"image",
"video",
"summary",
"content",
"keyword"
]
},
{
"id": "3",
"name": "Template Name 4",
"root": "root",
"entriesValue": [
"description",
"title",
"languageId",
"categoryIds"
]
}
]
At first input it work properly but in second input it passes the value in in both object
<image>
<imageid>Correct</imageid>
<type>bug</type>
<width>bug</width>
<hfive></hfive>``
</image>
<video>
<name>bug</name>
<type>bug</type>
<bitrate></bitrate>
<size></size>
<width></width>
<hfive></hfive>
<headline></headline>
<summary></summary>
</video>

Generic solution to create an Object of unknown deepth from an Array

I need to create a JSON object as follows:
{
"app_name": "foo",
"meta": {
"title": "foo",
"lang": "bar"
},
"teaser": {
"foo": {
"headline": "foo",
"subline": "bar"
}
}
}
The object tree is provided in the following representation:
var translations = [
{
"key": "app_name",
"val": "foo"
},
{
"key": "meta.title",
"val": "foo"
},
{
"key": "meta.lang",
"val": "bar"
},
{
"key": "teaser.foo.headline",
"val": "foo"
},
{
"key": "teaser.foo.subline",
"val": "bar"
}
];
Now, I can't find a generic solution at the moment. Here's some code that would work for the given (simplified) example:
var finalObject = {};
for (var i in translations) {
var translation = translations[i],
translationKey = translation["key"],
translationVal = translation["val"];
var keyArray = translationKey.split("."),
keyDepth = keyArray.length;
if (keyDepth === 1) {
finalObject[keyArray[0]] = translationVal;
} else if (keyDepth === 2) {
if (typeof finalObject[keyArray[0]] === 'object') {
finalObject[keyArray[0]][keyArray[1]] = translationVal;
} else {
var item = {};
item[keyArray[1]] = translationVal;
finalObject[keyArray[0]] = item;
}
} else if (keyDepth === 3) {
if (finalObject[keyArray[0]] && finalObject[keyArray[0]][keyArray[1]] && typeof finalObject[keyArray[0]][keyArray[1]] === 'object') {
finalObject[keyArray[0]][keyArray[1]][keyArray[2]] = translationVal;
} else {
var item = {};
item[keyArray[2]] = translationVal;
if (!finalObject[keyArray[0]] || typeof finalObject[keyArray[0]] !== 'object') {
finalObject[keyArray[0]] = {};
}
finalObject[keyArray[0]][keyArray[1]] = item;
}
}
}
But this is as ugly as unreliable. I'd like to replace this part:
if (keyDepth === 1) {
finalObject[keyArray[0]] = translationVal;
} else if (keyDepth === 2) {
//...
}
with
if (keyDepth === 1) {
finalObject[keyArray[0]] = translationVal;
} else {
//some generic solution, which works for any deepth
}
Any ideas?
You could take an iterative approach by using a default object if a property does not exists.
function setValue(object, key, value) {
var path = key.split('.'),
last = path.pop();
path.reduce(function (o, k) {
return o[k] = o[k] || {};
}, object)[last] = value;
}
var translations = [{ key: "app_name", val: "foo" }, { key: "meta.title", val: "foo" }, { key: "meta.lang", val: "bar" }, { key: "teaser.foo.headline", val: "foo" }, { key: "teaser.foo.subline", val: "bar" }],
object = {};
translations.forEach(function (o) {
setValue(object, o.key, o.val);
});
console.log(object);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sorting JSON Array by a double nested value?

I am unable to find a reasonable solution as I am pulling JSON data from firebase and pulling it from node.js into an html file. I want to sort my data via a property called "value" by not sure how to access a sub-sub-value to sort by in JQuery and am wondering if someone could help lead me in the right direction.
{
key: "a",
{
key: "ab",
{
value: 2
}
key: "ac",
{
value: 0
}
}
},
{
key: "b",
{
key: "bb",
{
value: 1
}
}
},
Output:
[{ac}, {bb}, {ab}]
Both your input and desired output are expressed in an invalid notation (both in JSON and JavaScript syntax), so I'll have to make some assumptions.
You could use this recursive function, which will find all nested value properties, and collect those values together with the names of the parent properties in which they occur. Finally those pairs of data (parent key and value) are sorted:
function collectValues(obj, name) {
return Object.entries(obj).reduce( (acc, [key, value]) => {
return acc.concat(
// recursively look into nested objects:
Object(value) === value ? collectValues(value, key)
// else, when key is 'value', collect that object
: key == 'value' ? [[name, value]]
// otherwise ignore this value
: []
)
}, []);
}
// Sample input
var input = [{
"a": {
"ab": {
value: 2
},
"ac": {
value: 0
}
}
}, {
"b": {
"bb": {
value: 1
}
}
}];
var result = collectValues(input).sort( (a,b) => a[1] - b[1] );
console.log(result);
Mocking up your JSON from the original image:
var data = {
key1: {
"a": { "deliveryshort": "12152017" },
"b": { "deliveryshort": "10122015" },
"c": { "deliveryshort": "11302016" },
"d": { "deliveryshort": "09022014" }
},
key2: {
"a": { "deliveryshort": "10102017" },
"b": { "deliveryshort": "09102017" }
},
};
function parseDate(dateStr) {
var month = "" + dateStr[0] + dateStr[1];
var day = "" + dateStr[2] + dateStr[3];
var year = "" + dateStr[4] + dateStr[5] + dateStr[6] + dateStr[7];
var result = new Date(year, month, day);
return result;
}
function sortBy(data, property, converter) {
var j = new Array();
for (var item in data) {
j.push([item, data[item], converter(data[item][property])]);
}
j.sort(function (a, b) { return a[2] - b[2] });
return j;
}
function sortData(data) {
var d = {};
for (var item in data) {
var sorted = sortBy(data[item], "deliveryshort", function (a) { return parseDate(a); });
/*var normalized = new Array();
for (var i = 0; i < sorted.length; i++) {
var ni = sorted[i];
var key = ni[0];
var obj = ni[1];
normalized[key] = obj;
}*/
d[item] = sorted;
}
console.log(d);
return d;
}
sortData(data);

How to get all key in JSON object (javascript)

{"document":
{"people":[
{"name":["Harry Potter"],"age":["18"],"gender":["Male"]},
{"name":["hermione granger"],"age":["18"],"gender":["Female"]},
]}
}
From this JSON example, I would like to get the keys such as name, age, gender for each people.
How to do this?
I use Object.keys which is built into JavaScript Object, it will return an array of keys from given object MDN Reference
var obj = {name: "Jeeva", age: "22", gender: "Male"}
console.log(Object.keys(obj))
Try this
var s = {name: "raul", age: "22", gender: "Male"}
var keys = [];
for(var k in s) keys.push(k);
Here keys array will return your keys ["name", "age", "gender"]
var input = {"document":
{"people":[
{"name":["Harry Potter"],"age":["18"],"gender":["Male"]},
{"name":["hermione granger"],"age":["18"],"gender":["Female"]},
]}
}
var keys = [];
for(var i = 0;i<input.document.people.length;i++)
{
Object.keys(input.document.people[i]).forEach(function(key){
if(keys.indexOf(key) == -1)
{
keys.push(key);
}
});
}
console.log(keys);
ES6 of the day here;
const json_getAllKeys = data => (
data.reduce((keys, obj) => (
keys.concat(Object.keys(obj).filter(key => (
keys.indexOf(key) === -1))
)
), [])
)
And yes it can be written in very long one line;
const json_getAllKeys = data => data.reduce((keys, obj) => keys.concat(Object.keys(obj).filter(key => keys.indexOf(key) === -1)), [])
EDIT: Returns all first order keys if the input is of type array of objects
var jsonData = { Name: "Ricardo Vasquez", age: "46", Email: "Rickysoft#gmail.com" };
for (x in jsonData) {
console.log(x +" => "+ jsonData[x]);
alert(x +" => "+ jsonData[x]);
}
This function should return an array of ALL the keys (i.e. the key names) in a JSON object including nested key/value pairs.
function get_all_json_keys(json_object, ret_array = []) {
for (json_key in json_object) {
if (typeof(json_object[json_key]) === 'object' && !Array.isArray(json_object[json_key])) {
ret_array.push(json_key);
get_all_json_keys(json_object[json_key], ret_array);
} else if (Array.isArray(json_object[json_key])) {
ret_array.push(json_key);
first_element = json_object[json_key][0];
if (typeof(first_element) === 'object') {
get_all_json_keys(first_element, ret_array);
}
} else {
ret_array.push(json_key);
}
}
return ret_array
}
Using this function on the OP's original object
const op_object =
{
"document":{
"people":[
{
"name":[
"Harry Potter"
],
"age":[
"18"
],
"gender":[
"Male"
]
},
{
"name":[
"hermione granger"
],
"age":[
"18"
],
"gender":[
"Female"
]
}
]
}
}
var all_keys = [];
function get_all_json_keys(json_object, ret_array = []) {
for (json_key in json_object) {
if (typeof(json_object[json_key]) === 'object' && !Array.isArray(json_object[json_key])) {
ret_array.push(json_key);
get_all_json_keys(json_object[json_key], ret_array);
} else if (Array.isArray(json_object[json_key])) {
ret_array.push(json_key);
first_element = json_object[json_key][0];
if (typeof(first_element) === 'object') {
get_all_json_keys(first_element, ret_array);
}
} else {
ret_array.push(json_key);
}
}
return ret_array
}
get_all_json_keys(op_object, all_keys);
console.log(all_keys);
should yield
[ 'document', 'people', 'name', 'age', 'gender' ]
Note: This will return a unique list of all key names.
We must "parse" our jsonObject
console.log('{"key0":"value0", "key1":"value1"}');
var jsonObject = JSON.parse('{"key0":"value0", "key1":"value1"}')
Object.keys(jsonObject).forEach(key => {
console.log(jsonObject[key]); //values
console.log(key); //keys
})

Categories

Resources