How to search JavaScript object and change value - javascript

Trying to understand JavaScript and writing to objects. I have an object here:
{
"name":"",
"children":[
{
"name":"Level 1",
"children":[
{
"name":"Level 2",
"children":[
{
"name":"Level 3",
"children":[
{
"name":"Level 4",
"children":[
{
"name":"Speed",
"children":null,
"id":6
}
],
"id":5
}
],
"id":4
}
],
"id":3
}
],
"id":2
},
{
"name":"Level 1",
"children":[
{
"name":"Level 2",
"children":[
{
"name":"Level 3",
"children":[
{
"name":"Level 4",
"children":[
{
"name":"Cost",
"children":null,
"id":11
}
],
"id":10
}
],
"id":9
}
],
"id":8
}
],
"id":7
},
{
"name":"Level 1",
"children":[
{
"name":"Level 2",
"children":[
{
"name":"Level 3",
"children":[
{
"name":"Level 4",
"children":[
{
"name":"Manufacturability",
"children":null,
"id":16
}
],
"id":15
}
],
"id":14
}
],
"id":13
}
],
"id":12
}
],
"id":1
}
and I'm trying to understand how to search for a given id value and change its name value.
In my case, I know that I can access values using d.id and d.name using the code below (this is part of a widget display; the name values populate it)
var jstring = this.model.get('value') ? this.model.get('value') : "{}";
// where 'value' = demo.json
var root = JSON.parse(jstring)
var g = this.g = svg.selectAll("g")
.data(partition.nodes(root))
.enter().append("g");
var path = this.path = g.append("path")
.attr("d", arc)
.style("fill", function(d) {
d.active = d.active ? true : false
return d.active || d.center ? color[1] : color[0];
})
.on("dblclick",dblclick);
var text = this.text = g.append("text")
.attr("transform", function(d) { return "rotate(" + computeTextRotation(d) + ")"; })
.attr("x", function(d) { return y(d.y); })
.attr("dx", "6") // margin
.attr("dy", ".35em") // vertical-align
.text(function(d) { return d.name; });
For example, if I click on a certain area on the widget, I can populate an input box by setting its value to d.name and it gives me the correct value.
function dblclick(d)
{
var input = document.getElementById("name");
input.value = d.name;
$( "#dialog" ).dialog(
{
buttons: {
Save: function() {
d.name = input.value;
var newString = JSON.stringify(root, function(key, val) {
if (Array.isArray(val)){
return val
}
if (val != null && typeof val == "object") {
val = _.pick(val, 'name', 'children', 'id');
if(d.id == val.id){
input.value = d.name;
console.log(d.name)
}
val.children = Array.isArray(val.children) ? val.children : [];
return val
}
return val
})
self.model.set('value', newString)
self.update()
console.log(newString)
I found a similar question here but I don't understand how to apply the answer to modify my JSON.
Also here is a fiddle of what I've tried: http://jsfiddle.net/CVvW4/237/ . I followed an answer from another question but my implementation is wrong.

Your jsonStr is already a json object, no need to stringify and parse it
You have a nested structure, to find something you will need a recursive function
Here is how to find a node given its id:
var root = jsonStr
function findById(node, id) {
if (node.id == id) return node; // we found the node with the id given, return it
var result = null; // if the id wasn´t the one we were looking, we need to look if it is in its children
if (node.children) {
for (var i = 0; i < node.children.length && result == null; i++) {
result = findById(node.children[i], id)
}
}
return result; // return null if it wasn´t in its children, return the node if it was
}
console.log(findById(root, 16))
Now, to change its name you can simply do:
findById(root, 16).name = 'asd';

I really like the accepted answer provided by #juvian which I up-voted.
I provide this one to show how you can name the child array and the property we wish to match on for the node. I also protect the array iteration by type.
I provide here some details regarding JSON, JavaScript Objects and when to parse, when not to parse by providing some examples of each.
Note that I added a small function typeName to assist in discovery of names and thus we do not attempt to iterate a non-array type (null one, string etc.) by the same name as the property we are searching for.
NOTE: I did NOT protect against the type matching of the property against the searchFor value but if that was important, string "1" vs number 1 you could put in an enhancement using the typeName as well.
Example to play with: https://jsfiddle.net/MarkSchultheiss/s4sxy4f6/
HERE is a stripped down version where I check for success prior to trying to assign the name to it: https://jsfiddle.net/MarkSchultheiss/s4sxy4f6/1/
Code and objects to show types:
// this is just a string, but special as it is a JSON string and can be parsed
var myJSON = '{"children":[{"children":[{"children":[{"children":[{"children":[{"children":null,"id":6,"name":"Speed"}],"id":5,"name":"Level 4"}],"id":4,"name":"Level 3"}],"id":3,"name":"Level 2"}],"id":2,"name":"Level 1"},{"children":[{"children":[{"children":[{"children":[{"children":null,"id":11,"name":"Cost"}],"id":10,"name":"Level 4"}],"id":9,"name":"Level 3"}],"id":8,"name":"Level 2"}],"id":7,"name":"Level 1"},{"children":[{"children":[{"children":[{"children":[{"children":null,"id":16,"name":"Manufacturability"}],"id":15,"name":"Level 4"}],"id":14,"name":"Level 3"}],"id":13,"name":"Level 2"}],"id":12,"name":"Level 1"}],"_default":{},"id":1,"name":""}';
// This is a JavaScript Object
var myObject = {
"children": [{
"children": [{
"children": [{
"children": [{
"children": [{
"children": null,
"id": 6,
"name": "Speed"
}],
"id": 5,
"name": "Level 4"
}],
"id": 4,
"name": "Level 3"
}],
"id": 3,
"name": "Level 2"
}],
"id": 2,
"name": "Level 1"
}, {
"children": [{
"children": [{
"children": [{
"children": [{
"children": null,
"id": 11,
"name": "Cost"
}],
"id": 10,
"name": "Level 4"
}],
"id": 9,
"name": "Level 3"
}],
"id": 8,
"name": "Level 2"
}],
"id": 7,
"name": "Level 1"
}, {
"children": [{
"children": [{
"children": [{
"children": [{
"children": null,
"id": 16,
"name": "Manufacturability"
}],
"id": 15,
"name": "Level 4"
}],
"id": 14,
"name": "Level 3"
}],
"id": 13,
"name": "Level 2"
}],
"id": 12,
"name": "Level 1"
}],
"_default": {},
"id": 1,
"name": ""
};
// just to get the name of the objects type from the object prototype
function typeName(obj) {
// splits and returns second part of string such as "[object Array]" returns the "Array" removing the closing bracket
return Object.prototype.toString.call(obj).match(/.* (.*)\]/)[1];
}
// show some type names to assist with object "type" education
console.log("myJSON:" + typeName(myJSON)); // String
console.log("myObject:" + typeName(myObject)); // Object
console.log("Children of object:" + typeName(myObject.children)); // Array
console.log("Children Type:" + typeof myObject["children"] + " typeName:" + typeName(myObject.children));
console.log(Object.keys(myObject)); // thus we can get the string "children" from the object with Object.keys(myObject)[0]
var root = JSON.stringify(myObject); // create string of object
console.log("root:" + typeName(root)); // String
var newObject = JSON.parse(myJSON); // create new object of string
// create function with private name to call internally
// done this way to allow for external modification of the name without need to change the code inside it.
var findByProperty = function findNext(node, searchValue, propertyName, childName) {
if (node.hasOwnProperty(propertyName) && node[propertyName] == searchValue) return node; // node found return it
var result = null;
// has child array by the name and it is non-empty array
if (node.hasOwnProperty(childName) && typeName(node[childName]) === 'Array' && node[childName].length) {
for (var i = 0; i < node[childName].length && result == null; i++) {
result = findNext(node[childName][i], searchValue, propertyName, childName);
}
}
return result; // return null if not in children, return the node if it was
}
var searchFor = 16;
console.log('searchFor is a type of:'+typeName(searchFor));
var propertyName = "id";
var childrenArrayName = "children";
// show how we can return the found node then modify it
var found = findByProperty(myObject, searchFor, propertyName, childrenArrayName);
found.name = 'Freddy';
console.log(myObject);
console.log(myObject["children"][2]["children"][0]["children"][0]["children"][0]["children"][0].name); // logs "Freddy"
var secondfound = findByProperty(newObject, searchFor, propertyName, childrenArrayName);
secondfound.name = 'Walter';// modify the object via the node
console.log(newObject);
console.log(newObject["children"][2]["children"][0]["children"][0]["children"][0]["children"][0].name); // logs "Walter"
// just to show that the actual object is the one found
console.log(secondfound.name === newObject["children"][2]["children"][0]["children"][0]["children"][0]["children"][0].name); // logs true
Here is the output of the console logs:
myJSON:String
VM78:125 myObject:Object
VM78:126 Children of object:Array
VM78:128 Children Type:object typeName:Array
VM78:129 ["children", "_default", "id", "name"]
VM78:132 root:String
VM205:148 searchFor is a type of:Number
VM281:153 Object {children: Array[3], _default: Object, id: 1, name: ""}
VM281:154 Freddy
VM337:158 Object {children: Array[3], _default: Object, id: 1, name: ""}
VM337:159 Walter
VM344:160 true

Related

How to create a new array by filtering only the necessary data?

I have an object which contains questions with different types multiple, single and text.
const data = {
questions: [
{
"question": "Question 1",
"value": [
"value_1.1.1",
"value_1.1.2"
],
"type": "multiple",
"options": [
{
"value": "value_1.1.1",
"label": "Value 1.1.1"
},
{
"textValue":"Additional text value",
"value": "value_1.1.2",
"label": "Value 1.1.2"
},
{
"value":"value_1.1.3",
"label":"Value 1.1.3",
}
]
},
{
"question": "Question 2",
"value": "value_2.1.1",
"type": "single",
"options": [
{
"value": "value_2.1.1",
"label": "Value 2.1.1"
},
{
"value": "value_2.1.2",
"label": "Value 2.1.2"
},
]
},
{
"question":"Question 3",
"textValue":"Test 12345",
"type":"text"
}
]
}
I want to create a new array with objects, which contains the question key and the value key.
The value key must contain the label of the selected options.
For a multiple type, the value can contain multiple labels.
The selected option can be retrieved from the parent value key, if it is equal to the value of the option, I want to use the label of this option as value.
In some cases an option also contains a textValue (see 1.1.3), then this must also be added to the value.
So the new array should look like this for the example above:
const newData = [
{
question: "Question 1",
value: ['Value 1.1.1', 'Value 1.1.2', 'Additional text value']
},
{
question: "Question 2",
value: ['Value 2.1.1']
},
{
question: "Question 3",
value: ['Test 12345']
}
];
Well basically loop over the questions, handling each by its own type. The tricky part is the type: multiple but it is managable.
Update: Fixed according to comment
const data = {questions:[{question:"Question 1",value:["value_1.1.1","value_1.1.2"],type:"multiple",options:[{value:"value_1.1.1",label:"Value 1.1.1"},{value:"value_1.1.2",label:"Value 1.1.2"},{textValue:"test12",value:"value_1.1.3",label:"Value 1.1.3"}]},{question:"Question 2",value:"value_2.1.1",type:"single",options:[{value:"value_2.1.1",label:"Value 2.1.1"},{value:"value_2.1.2",label:"Value 2.1.2"},]},{question:"Question 3",textValue:"Test 12345",type:"text"}]};
function get_option_label(options, value) {
return options.find(item => item.value == value).label || value
}
const newData = [];
data.questions.forEach(function(obj) {
var new_obj = {
question: obj.question
}
if (obj.type == "multiple") {
new_obj.value = JSON.parse(JSON.stringify(obj.value))
new_obj.value = new_obj.value.map(item => get_option_label(obj.options, item))
// add textValue for multiple question
// but only if its value is on parent
var objText = obj.options.find((item) => item.textValue);
if (objText && obj.value.indexOf(objText.value) >= 0) {
new_obj.value.push(objText.textValue)
}
}
if (obj.type == "single") {
new_obj.value = [get_option_label(obj.options, obj.value)]
}
if (obj.type == "text") {
new_obj.value = [obj.textValue]
}
newData.push(new_obj)
})
// now replacing all values with labels
console.log(newData);
.as-console-wrapper {
max-height: 100% !important;
top: 0
}

Filtering array of object using key in Javascript (node.js)

Please anyone can help, I want to filter data based on key in node.js, I've tried most of things, but didn't worked.
Below example data which needs to be filtered. I could able to filter key:value pair, nested Json object but filtering Array of json object is not working.
E.g. var data =
[{
"createdBy":"Tom"
"logistics" : 0,
"paymentStatus" : "Paid",
"orderAmount" : 5393.75,
"details" : {
"street": "S.S road",
"postCOde": "440111",
},
"subOrders" : [
{
"name" : "sub Product1",
"mrp" : 12,
"details": "desk"
},
{
"name" : "subProduct2",
"mrp" : 89,
"details": "chair"
}
]
}]
result object should be filtered based on given permission array
var permissionArray = ['logistics','paymentStatus','details.street','subOrders.name','subOrders.details'];
filtered result should look like
{
result = [{
"logistics" : 0,
"paymentStatus" : "Paid",
"details" : {
"street": "S.S road",
},
"subOrders" : [
{
"name" : "sub Product1",
"details" : "desk"
},
{
"name" : "sub Product1",
"details" : "chair"
}
]
}]
}
Building on #radulle's answer to allow the 'details.name' dot notation desired:
(Also updated to now allow multiple subfields of one field - like 'subOrders.name' and 'subOrders.details')
var arr =
[{
"createdBy":"Tom",
"logistics" : 0,
"paymentStatus" : "Paid",
"orderAmount" : 5393.75,
"details" : {
"street": "S.S road",
"postCode": "440111"
},
"subOrders" : [
{
"name" : "sub Product1",
"mrp" : 12,
"details": "desk"
},
{
"name" : "subProduct2",
"mrp" : 89,
"details": "chair"
}
]
}]
var permissionArray = ['logistics','paymentStatus','details.street', 'details.postCode','subOrders.name', 'subOrders.details'];
var arrFiltered = arr.map(el => {
let newEl = {}
for (let elm of permissionArray){
if (elm.includes('.')){
//console.log(elm);
const split_arr = elm.split('.')
//console.log(el[split_arr[0]]);
if (el[split_arr[0]] instanceof Array){
if (!newEl.hasOwnProperty([split_arr[0]]) ){
newEl[split_arr[0]] = el[split_arr[0]].map((child,index) => ({[split_arr[1]]: child[split_arr[1]]}) )
} else {
el[split_arr[0]].forEach((child,index) => {
//console.log(child[ split_arr[1] ]);
newEl[split_arr[0]][index][split_arr[1]] = child[split_arr[1]];
})
}
} else{
if (!newEl.hasOwnProperty([split_arr[0]]) ){
newEl[split_arr[0]] = {[split_arr[1]]: el[split_arr[0]][split_arr[1]]}
} else {
newEl[split_arr[0]][split_arr[1]] = el[split_arr[0]][split_arr[1]];
}
}
} else {
newEl[elm] = el[elm];
}
}
return newEl;
}
)
console.log(arrFiltered)
.as-console-wrapper { max-height: 100% !important; top: 0; }
NOTE: you need to check first if a dot is included with elm.includes('.'), then you have to split it into its two parts with elm.split('.'), then finally you need to check if the value of the key is an array, like 'subOrders' or if it is just an object like 'details' and handle each case with either directly calling the child key, or mapping over the array and calling the child key.
With the permission array as:
var permissionArray = ['logistics','paymentStatus','details.street', 'details.postCode','subOrders.name', 'subOrders.details'];
The output is:
[
{
"logistics": 0,
"paymentStatus": "Paid",
"details": {
"street": "S.S road",
"postCode": "440111"
},
"subOrders": [
{
"name": "sub Product1",
"details": "desk"
},
{
"name": "subProduct2",
"details": "chair"
}
]
}
]
NOTE: upon request of the OP, this now also allows you to have two subfields of one field like 'subOrders.name', 'subOrders.details'
For this !newEl.hasOwnProperty([split_arr[0]]) is used to check if the property/key doesn't already exist. If it does not, then create it, but if it does, then modify this existing property/key's value/item.
You could take a two step approach where you group same keys in an array and store the nested properties as well to the grouped parents.
This is important if you have same parent keys, like
['subOrders.name', 'subOrders.mrp']
For example a grouped array looks like this:
[
[
"logistics"
],
[
"paymentStatus"
],
[
"details",
["street"]
],
[
"subOrders",
["name", "mrp"]
]
]
Then build new objects based on the key and nested keys.
function filter(keys) {
var pathes = keys.reduce((r, path) => {
var [key, ...rest] = path.split('.'),
temp = r.find(([q]) => q === key);
if (rest.length)
if (temp) temp[1].push(rest.join('.'));
else r.push([key, [rest.join('.')]]);
else
if (!temp) r.push([key]);
return r;
}, []);
return function (object) {
const keys = pathes.filter(([key]) => key in object);
return Object.fromEntries(keys.map(([key, rest]) => [
key,
rest
? Array.isArray(object[key])
? object[key].map(filter(rest))
: filter(rest)(object[key])
: object[key]
]));
};
}
var permissionArray = ['foo', 'logistics', 'paymentStatus', 'details.street', 'subOrders.name'],
data = [{ createdBy: "Tom", logistics: 0, paymentStatus: "Paid", orderAmount: 5393.75, details: { street: "S.S road", postCOde: "440111", }, subOrders: [{ name: "sub Product1", mrp: 12 }, { name: "subProduct2", mrp: 89 }] }],
result = data.map(filter(permissionArray));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Instead of building a filtered output, we may operate on original obj and remove its props.
The permissions represent a tree (or trie if node is a word (. delimited))
If we further assume that any specified path is accessible in data, then any leaf has for parent an array or object (and so forth).
We then build a tree, and for any node traverse data and remove the keys which are not part of our specification.
const data = {"createdBy":"Tom","logistics":0,"paymentStatus":"Paid","orderAmount":5393.75,"details":{"street":"S.S road","postCOde":"440111"},"subOrders":[{"name":"sub Product1","mrp":12},{"name":"subProduct2","mrp":89}],"a":{"b":[{"c":3,"d":"a"},{"c":4,"e":"f"}]}}
const d = JSON.parse(JSON.stringify(data)) // do not mutate original
const v = ['logistics','paymentStatus','details.street','subOrders.name','subOrders.details','a.b.c']
const tree = v.map(x => x.split('.')).reduce((o, p) => {
p.reduce((c, x) => (c[x] = c[x] || {}), o)
return o
},{})
function rec (keep, node) {
if (Object.keys(keep).length === 0) return
if (Array.isArray(node)) { return node.forEach(rec.bind(0, keep)) }
for (const k in node) {
!(k in keep) ? delete node[k] : rec(keep[k], node[k])
}
}
rec(tree, d)
console.log(JSON.stringify(d,null,2))
You can maybe do it like this:
var arr =
[{
"createdBy":"Tom",
"logistics" : 0,
"paymentStatus" : "Paid",
"orderAmount" : 5393.75,
"details" : {
"street": "S.S road",
"postCOde": "440111"
},
"subOrders" : [
{
"name" : "sub Product1",
"mrp" : 12
},
{
"name" : "subProduct2",
"mrp" : 89
}
]
}]
var permissionArray = ['logistics','paymentStatus','details']
var arrFiltered = arr.map(el => {
let newEl = {}
for (let elm of permissionArray) newEl[elm] = el[elm]
return newEl
}
)
console.log(arrFiltered)
In the following solution, we divide the handling of objects and plain arrays.
We build-up a "qualified key" corresponding to the equivalent string in the permissions array, as we recursively descend into an object along its properties.
If we hit a primitive value, then we end the recursion for that property.
A new object sanitized is created for each level of the recursion to contain only the permitted properties.
const data = [{ "createdBy": "Tom", "logistics": 0, "paymentStatus": "Paid", "orderAmount": 5393.75, "details": { "street": "S.S road", "postCOde": "440111" }, "subOrders": [{ "name": "sub Product1", "mrp": 12 }, { "name": "subProduct2", "mrp": 89 }] }]
const isPrimitive = (x)=>x === null || typeof x !== "object"
function sanitize(o, permissions, prefix='') {
if (isPrimitive(o)) return o
const sanitized = {}
for (const[k,v] of Object.entries(o)) {
const qk = `${prefix}${k}`
if (permissions.some((p)=>p.match(new RegExp(`^${qk}`)))) {
sanitized[k] = Array.isArray(v)
? sanitizeArray(v, permissions, `${qk}.`)
: sanitize(v, permissions, `${qk}.`)
}
}
return sanitized
}
const sanitizeArray = (arr,permissions,prefix='')=>arr.map((el)=>sanitize(el, permissions, prefix))
const permissions = ['logistics', 'paymentStatus', 'details.street', 'subOrders.name']
const sanitized = sanitizeArray(data, permissions)
console.log(sanitized)

How to remove complete unique value from array [duplicate]

This question already has answers here:
How to remove all duplicates from an array of objects?
(77 answers)
Closed 3 years ago.
How to remove complete record of same object in array please help me this, I am using below funtion but its only remove one value I want remove complete object of same object
var data = [{
"QuestionOid": 1,
"name": "hello",
"label": "world"
}, {
"QuestionOid": 2,
"name": "abc",
"label": "xyz"
}, {
"QuestionOid": 1,
"name": "hello",
"label": "world"
}];
function removeDumplicateValue(myArray) {
var newArray = [];
$.each(myArray, function (key, value) {
var exists = false;
$.each(newArray, function (k, val2) {
if (value.QuestionOid == val2.QuestionOid) { exists = true };
});
if (exists == false && value.QuestionOid != undefined) { newArray.push(value); }
});
return newArray;
}
I want result like this
[{
"QuestionOid": 2,
"name": "abc",
"label": "xyz"
}]
You can use reduce.
var data = [{"QuestionOid": 1,"name": "hello","label": "world"}, {"QuestionOid": 2,"name": "abc","label": "xyz"}, {"QuestionOid": 1,"name": "hello","label": "world"}];
let op = data.reduce((op,inp)=>{
if(op[inp.QuestionOid]){
op[inp.QuestionOid].count++
} else {
op[inp.QuestionOid] = {...inp,count:1}
}
return op
},{})
let final = Object.values(op).reduce((op,{count,...rest})=>{
if(count === 1){
op.push(rest)
}
return op
},[])
console.log(final)
Do with Array#filter.Filter the array matching QuestionOid value equal to 1
var data = [{ "QuestionOid": 1, "name": "hello", "label": "world" }, { "QuestionOid": 2, "name": "abc", "label": "xyz" }, { "QuestionOid": 1, "name": "hello", "label": "world" }]
var res = data.filter((a, b, c) => c.map(i => i.QuestionOid).filter(i => i == a.QuestionOid).length == 1)
console.log(res)

How to access a specific element in nested array in JSON data using JavaScript?

I have JSON data which is structured as below. Intension is to look up a specific datapoint, e.g. annual profit, which is 5000.
I want to do this by finding the column by name, e.g. "profit", identify the column index (3 in the example), and then use the column index to select the nth (3rd) element in the second node ("annual") of the "data" array.
How can I do this using the findIndex() function in Javascript (see the key part of my code below)?
JSON data:
{
"datatable": {
"data": [
[
"AAPL",
"quarterly",
1000,
2000
],
[
"AAPL",
"annual",
5000,
10000
]
],
"columns": [{
"name": "ticker"
"type": "String"
},
{
"name": "timedim"
"type": "String"
},
{
"name": "profit",
"type": "Integer"
},
{
"name": "revenue",
"type": "Integer"
}
]
}
}
JavaScript code:
// daten contains the "data" array of the JSON dataset
// spalten contains the "columns" array of the JSON dataset
var i = spalten.findIndex(obj => obj.name == "profit");
output += '<p>Annual profit AAPL: ' + daten[i] + '</p>';
elroot.innerHTML += output;
You have 2-dimensional array, so, you need two indexes:
const json = {
"datatable": {
"data": [
[
"AAPL",
"quarterly",
1000,
2000
],
[
"AAPL",
"annual",
5000,
10000
]
],
"columns": [{
"name": "ticker",
"type": "String"
},
{
"name": "timedim",
"type": "String"
},
{
"name": "profit",
"type": "Integer"
},
{
"name": "revenue",
"type": "Integer"
}
]
}
}
var profitIndex = json.datatable.columns.findIndex(item => item.name == 'profit');
var annualIndex = json.datatable.data.findIndex(array => array.indexOf('annual') > -1);
var annualProfit = json.datatable.data[annualIndex][profitIndex];
If you need a function, it could look like below:
var getValueFromJson = function (json, columnName, dataMarker) {
var columnIndex = json.datatable.columns.findIndex(item => item.name == columnName);
var dataMarkerIndex = json.datatable.data.findIndex(array => array.indexOf(dataMarker) > -1);
if (columnIndex < 0 || dataMarkerIndex < 0) {
return null;
}
return json.datatable.data[dataMarkerIndex][columnIndex];
}
console.log(getValueFromJson(json, 'profit', 'quarterly'));
console.log(getValueFromJson(json, 'profit', 'annual'));
console.log(getValueFromJson(json, 'revenue', 'quarterly'));
console.log(getValueFromJson(json, 'revenue', 'annual'));
Above code prints:
> 1000
> 5000
> 2000
> 10000
Based on the JSON structure you've given, the following will work. Writing a function would be good if you want to get specific profit based on parameters.
var output = ""
function getProfit(type="annual", column=2) {
var arrForType = yourData.datatable.data.find(arr => arr.indexOf(type) !== -1);
return arrForType[column];
}
var i = yourData.datatable.columns.findIndex(obj => obj.name == "profit");
output += '<p>Annual profit AAPL: ' + getProfit("annual", i) + '</p>';
document.body.innerHTML += output;
You don't need findIndex - just use find and includes like so:
const data = {
"datatable": {
"data": [
[
"AAPL",
"quarterly",
1000,
2000
],
[
"AAPL",
"annual",
5000,
10000
]
],
"columns": [{
"name": "ticker",
"type": "String"
},
{
"name": "timedim",
"type": "String"
},
{
"name": "profit",
"type": "Integer"
},
{
"name": "revenue",
"type": "Integer"
}
]
}
};
function findValue(type) {
return data.datatable.data.find(e => e.includes(type))[2];
}
console.log(findValue("annual"));
console.log(findValue("quarterly"));
This is the basic idea, then if you need to scale obviously you'll need to do this in a nicer way.
let output = '';
// Searches the desired index (refactor as needed)
const index = spalten.findIndex(obj => obj.name == "profit")
// Extract all the profits (if you dont need all just select the desired one)
daten.map(item => output += `<p>${item[1]} profit ${item[0]}: ${item[index]}</p>`)

Javascript Get the parent id from a sub id

I have some code that will return me the name of the subcat clicked.
Here is the data below:
theData = {
"categories": [
{
"id": "661",
"name": "some name",
"description": "some description",
"subcat": [
{
"id": "662",
"name": "sub 1",
"translations": null
},
{
"id": "663",
"name": "sub 2",
"translations": null
}
],
"image": null
},
{
"id": "657",
"name": "some other name",
"description": "",
"subcat": [
{
"id": "456",
"name": "sub 12",
"translations": null
},
{
"id": "656",
"name": "sub 15",
"translations": null
}
],
"image": null
}
]
};
I need some way to find the parent id of the subcat name.
For example if I gave it "sub 15", it would return "661" which is the parent id
How can I do this?
There's no way by default to access the "parent" of an object in Javascript -- it could be referenced in any number of other objects, or even by itself, so it's not possible to determine what the sole parent of an object is.
Instead, we'll just iterate through all the data until we find the matching id, and return null if we never find it. This solution counts on your IDs being unique entities, so if that's not the case, it'll have to be changed. With that said, here's an example:
function getParent(subID) {
for (var i in theData.categories) {
var parent = theData.categories[i];
if ('subcat' in parent && 'length' in parent.subcat) {
for (var j = 0; j < parent.subcat.length; j++) {
if (parent.subcat[j].id === subID) {
return parent.id;
}
}
}
}
return null;
}
If you don't like your function returning null, you can always alter it so that it returns -1, assuming that -1 is out-of-band for your IDs. Note also that this is hardly an optimal solution, so if you're intending to use this for large amounts of data, you'll want to look into faster and/or more efficient search algorithms.
try this .we have to iterate through all the data
[fiddle][1]
Fiddle
var input = "sub 15";
var id =-1;
for(var i=0;i<theData.categories.length;i++){
if(theData.categories[i].subcat!=null){
for(var j=0;j<theData.categories[i].subcat.length;j++){
if(theData.categories[i].subcat[j].name==input){
id= theData.categories[i].id;
break;
}
}
}
}
console.log(id)
You might consider more a generic solution, which searches for a given key and a value in the subcat array. Then take only the first object's id.
function getParentId(key, value) {
return (theData.categories.filter(function (a) {
return a.subcat.some(function (b) {
return b[key] === value;
});
})[0] || {}).id;
}
var theData = { categories: [{ id: 661, name: "some name", description: "some description", subcat: [{ id: 662, name: "sub 1", translations: null }, { id: 663, name: "sub 2", translations: null }], image: null }, { id: 657, name: "some other name", description: 0, subcat: [{ id: 456, name: "sub 12", translations: null }, { id: 656, name: "sub 15", translations: null }], image: null }] };
console.log(getParentId('name', 'sub 15'));
This may not be the best way but hope this will be useful
var getSubCat = []; // create an empty array to map parent id with sub name
var getCat = theData.categories; // get categories
getCat.forEach(function(item) { // loop through categories
item.subcat.forEach(function(elem) {
getSubCat.push({
id: item.id, // this is parent id
sub: elem.name // name inside each subcat object. Total 4 subcat object
});
})
})
var parentId = getSubCat.filter(function(elem){ // filter the getSubCat array
return elem.sub ==='sub 15'
})[0].id // parentId is an array, we need first object so [0]
alert(parentId)
Now I am pushing name inside each of subcat object. On requirement you can also push their id
DEMO
The below solution looks similar to furkle's solution. But here it uses jquery to iterate through the json objects.
function getParent(subID) {
var parentId = null;
$.each(theData.categories, function(i, v)
{
$.each(v.subcat, function(idx, obj){
if(obj.name ==subID)
parentId = v.id
})
})
return parentId;
}

Categories