javascript recursive function giving error - javascript

I have my JSON structured like below which has the next and previous properties of an array of keys from the same structure.
{
"e6e1de44-d53b-44ae-9d52-8f6e1358f8ec": {
"course": "Semester 1",
"status": "completed",
"next": [
"d1fc647b-ad7e-4b72-9269-5559948ee61d"
],
"previous": [],
},
"d1fc647b-ad7e-4b72-9269-5559948ee61d": {
"course": "Semester 2",
"status": "completed",
"next": [
"cb00b200-cee3-4ab8-af11-abb7ea26183b",
"7b958370-d697-4536-9bff-fa564a5688ef"
],
"previous": [
"e6e1de44-d53b-44ae-9d52-8f6e1358f8ec"
],
},
"cb00b200-cee3-4ab8-af11-abb7ea26183b": {
"course": "Semester 3",
"status": "active",
"next": [
"72488692-064c-436c-93cb-8ebe2be7e168"
],
"previous": [
"d1fc647b-ad7e-4b72-9269-5559948ee61d"
],
},
"7b958370-d697-4536-9bff-fa564a5688ef": {
"course": "Semester 4",
"status": "active",
"next": [
"72488692-064c-436c-93cb-8ebe2be7e168"
],
"previous": [
"d1fc647b-ad7e-4b72-9269-5559948ee61d"
],
},
"72488692-064c-436c-93cb-8ebe2be7e168": {
"course": "Final",
"status": "not-started",
"next": [],
"previous": [
"cb00b200-cee3-4ab8-af11-abb7ea26183b",
"7b958370-d697-4536-9bff-fa564a5688ef"
],
}
}
I am trying to get the next array and the previous array recursively but it is giving me an error TypeError: Cannot read properties of undefined (reading 'recursiveFunc') I'm calling a function like this.
let nextRes = [];
recursiveFunc(courseData, 'e6e1de44-d53b-44ae-9d52-8f6e1358f8ec', nextRes, true);
let prevRes = [];
recursiveFunc(courseData, 'cb00b200-cee3-4ab8-af11-abb7ea26183b', prevRes, false);
I was wondering if the same function could be used to achieve a similar result. It is just a matter of traversing forward or backward. How can I get the id of the next data recursively?
nextRes shuld have populated ['d1fc647b-ad7e-4b72-9269-5559948ee61d', 'cb00b200-cee3-4ab8-af11-abb7ea26183b', '7b958370-d697-4536-9bff-fa564a5688ef', '72488692-064c-436c-93cb-8ebe2be7e168'] and prevRes like ['d1fc647b-ad7e-4b72-9269-5559948ee61d', 'e6e1de44-d53b-44ae-9d52-8f6e1358f8ec']
function recursiveFunc(data, parId, acc, forward) {
for (let property in data) {
if (data.hasOwnProperty(property) && typeof data[property] === 'object') {
var current = data[property];
if (forward && property == parId && typeof current.preReqStages === 'object' && data[property].next.length > 0) {
acc.push(current.next);
} else if (!forward && property == parId && typeof current.preReqStages === 'object' && data[property].previous.length > 0) {
acc.push(current.previous);
} else {
this.recursiveFunc(data, property, acc, forward)
}
}
}
}

Starting in order of your code, first you don't need to validate data.hasOwnProperty(property) if you're making a for of the properties in data.
Second, your validation of typeof current.preReqStages === 'object' should be typeof current.next === 'object' or current.previous for the next if, since you don't have a value of preReqStages.
Then, you are adding current.next to your array, meaning you're adding an array inside an array, when you only want the value, so I added a forEach and added each value.
And then the recursion should be inside the matches, because what you want to get is all the chain of courses, meaning that when you get the next one, you need to get the next one of that new property. So I made the recursion inside the forEach.
Here's the final result:
const courseData = {
"e6e1de44-d53b-44ae-9d52-8f6e1358f8ec": {
"course": "Semester 1",
"status": "completed",
"next": [
"d1fc647b-ad7e-4b72-9269-5559948ee61d"
],
"previous": [],
},
"d1fc647b-ad7e-4b72-9269-5559948ee61d": {
"course": "Semester 2",
"status": "completed",
"next": [
"cb00b200-cee3-4ab8-af11-abb7ea26183b",
"7b958370-d697-4536-9bff-fa564a5688ef"
],
"previous": [
"e6e1de44-d53b-44ae-9d52-8f6e1358f8ec"
],
},
"cb00b200-cee3-4ab8-af11-abb7ea26183b": {
"course": "Semester 3",
"status": "active",
"next": [
"72488692-064c-436c-93cb-8ebe2be7e168"
],
"previous": [
"d1fc647b-ad7e-4b72-9269-5559948ee61d"
],
},
"7b958370-d697-4536-9bff-fa564a5688ef": {
"course": "Semester 4",
"status": "active",
"next": [
"72488692-064c-436c-93cb-8ebe2be7e168"
],
"previous": [
"d1fc647b-ad7e-4b72-9269-5559948ee61d"
],
},
"72488692-064c-436c-93cb-8ebe2be7e168": {
"course": "Final",
"status": "not-started",
"next": [],
"previous": [
"cb00b200-cee3-4ab8-af11-abb7ea26183b",
"7b958370-d697-4536-9bff-fa564a5688ef"
],
}
}
function recursiveFunc(data, parId, acc, forward) {
for (let property in data) {
if (typeof data[property] === 'object') {
var current = data[property];
if (forward && property == parId && typeof current.next === 'object' && current.next.length > 0) {
current.next.forEach(n => {
if (!acc.includes(n)) {
acc.push(n)
this.recursiveFunc(data, n, acc, forward)
}
});
} else if (!forward && property == parId && typeof current.previous === 'object' && current.previous.length > 0) {
current.previous.forEach(p => {
if (!acc.includes(p)) {
acc.push(p)
this.recursiveFunc(data, p, acc, forward)
}
});
}
}
}
}
let nextRes = [];
recursiveFunc(courseData, 'e6e1de44-d53b-44ae-9d52-8f6e1358f8ec', nextRes, true);
console.log(nextRes)
let prevRes = [];
recursiveFunc(courseData, 'cb00b200-cee3-4ab8-af11-abb7ea26183b', prevRes, false);
console.log(prevRes)

Related

How do I find an element of an array in NiFi ExecuteScript (ECMAScript)?

I have a need to get data out of a NiFi flow file with somewhat complex JSON content. I'm planning to use a NiFi ExecuteScript processor because I don't think it can be done with EvaluateJSONPath. The content looks like this (snippet)
...
"segments": [
{
"INS01": "Y",
"INS03": "001",
"INS02": "18",
"INS05": "A",
"id": "INS",
"INS04": "AI",
"INS08": "FT"
},
{
"REF02": "1041558xxxxx",
"REF01": "0F",
"id": "REF"
},
{
"REF02": "ABD",
"REF01": "1L",
"id": "REF"
},
{
"REF02": "106835xxxxx",
"REF01": "23",
"id": "REF"
}
],
...
I want to extract the REF02 property value from the segments array element that has REF01 === '0F'. The array element does not necessarily have a REF02 property. So in the above case, I should get 1041558xxxxx.
Here's my current script:
var flowFile = session.get()
if (flowFile != null) {
var InputStreamCallback = Java.type('org.apache.nifi.processor.io.InputStreamCallback')
var IOUtils = Java.type('org.apache.commons.io.IOUtils')
var StandardCharsets = Java.type('java.nio.charset.StandardCharsets')
try {
var subscriber = null
session.read(flowFile,
new InputStreamCallback(function (inputStream) {
var data = JSON.parse(IOUtils.toString(inputStream, StandardCharsets.UTF_8))
var segment = data.segments.find(function (s) { return s.hasOwnProperty('REF01') && s.REF01 === '0F' })
subscriber = segment ? segment.REF02 : null
}));
session.putAttribute(flowFile, 'subscriber', subscriber ? subscriber : '')
session.transfer(flowFile, REL_SUCCESS)
} catch (e) {
log.error('script failed', e)
session.transfer(flowFile, REL_FAILURE)
}
}
When I execute the above, I get a java.lang.NoSuchMethodException. Also, are anonymous 'arrow' functions allow?
I've tried using an old-school for loop to no avail.
Thanks for your help.
You can add a JoltTransformJSON processor with specification
[
{
"operation": "shift",
"spec": {
"segments": {
"*": {
"REF01": {
"0F": {// conditional to match "REF01" with "0F"
"#2,REF02": ""// go two levels up the three to reach the level of the attributes REF01 or REF02
}
}
}
}
}
}
]
in order to return the result
"1041558xxxxx"
You can use below JSONPath with EvaluateJSONPath processor:
$.segments[?(#.REF01<="0F")]#.REF02
Note: Returned result is in the array, So you can use SplitJSON after that to get your string.
Groovy script:
import org.apache.commons.io.IOUtils
import java.nio.charset.StandardCharsets
import groovy.json.JsonSlurper
flowFile = session.get()
if(!flowFile) return
def jsonSlurper = new JsonSlurper()
def subscriber = ""
flowFile = session.write(flowFile, {inputStream, outputStream ->
input = IOUtils.toString(inputStream, StandardCharsets.UTF_8)
json = jsonSlurper.parseText(input)
segment = json.segments.find{ segment ->
if (segment.keySet().contains('REF01')) {
if (segment.REF01 == '0F') {
return true
} else {
return false
}
} else {
return false
}
}
if (segment) {
subscriber = segment.REF02
}
outputStream.write(input.getBytes(StandardCharsets.UTF_8))
} as StreamCallback)
session.putAttribute(flowFile, 'subscriber', subscriber)
session.transfer(flowFile, REL_SUCCESS)
input:
{
"test": "best",
"segments": [
{
"INS01": "Y",
"INS03": "001",
"INS02": "18",
"INS05": "A",
"id": "INS",
"INS04": "AI",
"INS08": "FT"
},
{
"REF02": "1041558xxxxx",
"REF01": "0F",
"id": "REF"
},
{
"REF02": "ABD",
"REF01": "1L",
"id": "REF"
},
{
"REF02": "106835xxxxx",
"REF01": "23",
"id": "REF"
}
]
}
output (with attribute subscriber: 1041558xxxxx):
{
"test": "best",
"segments": [
{
"INS01": "Y",
"INS03": "001",
"INS02": "18",
"INS05": "A",
"id": "INS",
"INS04": "AI",
"INS08": "FT"
},
{
"REF02": "1041558xxxxx",
"REF01": "0F",
"id": "REF"
},
{
"REF02": "ABD",
"REF01": "1L",
"id": "REF"
},
{
"REF02": "106835xxxxx",
"REF01": "23",
"id": "REF"
}
]
}

How can I update this nested object's value if one of its properties match in JS?

I saw many answers, but I haven't been able to modify any to my need.
Object
{
"id": "476ky1",
"custom_id": null,
"name": "Reunião com o novo Gerente de Vendas - Airton",
"text_content": null,
"description": null,
"status": {
"id": "p3203621_11svBhbO"
},
"archived": false,
"creator": {
"id": 3184709
},
"time_spent": 0,
"custom_fields": [{
"id": "36c0de9a-9243-4259-ba57-bd590ba07fe0",
"name": "Comments",
"value": "dsdsdsds"
}],
"attachments": []
}
Within custom_fields, if the property name's value is Comments, update the value property.
I've tried it like this, using this approach, for example, but it doesn't produce the expected result.
const updatedComment = [{ name: "Comments", value: "The comment is updated"}];
updateNestedObj(taskData, updatedComment)
function updateNestedObj(obj, updates) {
const updateToApply = updates.find(upd => upd.id === obj.id);
if (updateToApply) {
obj.title = updateToApply.content;
obj.note = updateToApply.note;
}
// Apply updates to any child objects
for(let k in obj) {
if (typeof(obj[k]) === 'object') {
updateNestedObj(obj[k], updates);
}
}
}
You're using the wrong property names when you search updates for updateToApply, and then when assigning the value.
When you recurse on children, you need to distinguish between arrays and ordinary objects, so you can loop over the nested arrays. You also have to skip null properties, because typeof null == 'object'.
const updatedComment = [{
name: "Comments",
value: "The comment is updated"
}];
function updateNestedObj(obj, updates) {
let updateToApply = updates.find(upd => upd.name == obj.name);
if (updateToApply) {
obj.value = updateToApply.value;
}
// Apply updates to any child objects
Object.values(obj).forEach(child => {
if (Array.isArray(child)) {
child.forEach(el => updateNestedObj(el, updates));
} else if (typeof(child) === 'object' && child != null) {
updateNestedObj(child, updates);
}
});
}
const taskData = {
"id": "476ky1",
"custom_id": null,
"name": "Reunião com o novo Gerente de Vendas - Airton",
"text_content": null,
"description": null,
"status": {
"id": "p3203621_11svBhbO"
},
"archived": false,
"creator": {
"id": 3184709
},
"time_spent": 0,
"custom_fields": [{
"id": "36c0de9a-9243-4259-ba57-bd590ba07fe0",
"name": "Comments",
"value": "dsdsdsds"
}],
"attachments": []
};
updateNestedObj(taskData, updatedComment)
console.log(taskData);
Try this:
const updatedComment = [{ name: "Comments", value: "A new comment value" }]
// you can add as many updates as you want
function update(obj, updates) {
for (const update in updates) {
for (const field in obj.custom_fields) {
if (obj.obj.custom_fields.name == update.name) {
obj.obj.custom_fields.value = update.value
}
}
}
}
update(obj, updatedComment)

Remove null value and key form JSON Object Javascript

In my case i need a function that remove the null and undefined key parameters from the object a function that transforms this object
Purpose
i am creating this long json object from mongo DB i am saving this and and creating XML from this for voice response
{
"say": {
"value": null
},
"play": {
"value": null
},
"dial": {
"value": "7597365803",
"options": {
"action": null,
"answerOnBridge": false,
"callerId": null,
"hangupOnStar": false,
"method": "GET",
"record": true,
"recordingStatusCallback": "false",
"recordingStatusCallbackMethod": "POST",
"recordingStatusCallbackEvent": "completed",
"recordingTrack": "both",
"ringTone": null,
"timeLimit": 14400,
"timeout": 30,
"trim": "do-not-trim",
"_id": "60cc1977c86fe21910ccbc85",
"__v": 0
}
},
"record": {
"value": null
},
"gather": {
"value": null
},
"pause": {
"value": null
},
"redirect": {
"value": null
},
"reject": {
"options": null
},
"number": {
"value": null
},
"user_id": "2",
"hangup": null,
"_id": "60cc0c416349282be4ed2f16",
"__v": 0
}
into this
{
"dial": {
"value": "7597365803",
"options": {
"action": null,
"answerOnBridge": false,
"callerId": null,
"hangupOnStar": false,
"method": "GET",
"record": true,
"recordingStatusCallback": "false",
"recordingStatusCallbackMethod": "POST",
"recordingStatusCallbackEvent": "completed",
"recordingTrack": "both",
"ringTone": null,
"timeLimit": 14400,
"timeout": 30,
"trim": "do-not-trim"
}
}
}
i created this function
function cleanObject (obj: any) {
Object.keys(obj).forEach(k =>
(obj[k] && typeof obj[k] === 'object') && this.cleanObject(obj[k]) ||
(!obj[k] && obj[k] !== undefined) && delete obj[k]
)
return obj
}
but it only solve and some problem and do not run well i tried lodash but it won't help
please help me i ma stuck
here is a solution with recursion. also, pls check see this, there are a couple of solutions with recursion are present there too.
const data = {
"say": {
"value": null
},
"play": {
"value": null
},
"dial": {
"value": "7597365803",
"options": {
"action": null,
"answerOnBridge": false,
"callerId": null,
"hangupOnStar": false,
"method": "GET",
"record": true,
"recordingStatusCallback": "false",
"recordingStatusCallbackMethod": "POST",
"recordingStatusCallbackEvent": "completed",
"recordingTrack": "both",
"ringTone": null,
"timeLimit": 14400,
"timeout": 30,
"trim": "do-not-trim",
"_id": "60cc1977c86fe21910ccbc85",
"__v": 0
}
},
"record": {
"value": null
},
"gather": {
"value": null
},
"pause": {
"value": null
},
"redirect": {
"value": null
},
"reject": {
"options": null
},
"number": {
"value": undefined
},
"user_id": "2",
"hangup": null,
"_id": "60cc0c416349282be4ed2f16",
"__v": 0
}
function removeEmpty(obj) {
const newObj = {};
Object.keys(obj).forEach(function(k) {
if (obj[k] && typeof obj[k] === "object") {
const value = removeEmpty(obj[k]);
if (Object.keys(value).length != 0) {
newObj[k] = removeEmpty(obj[k]);
}
} else if (obj[k] != null && obj[k] != undefined) {
newObj[k] = obj[k];
}
});
return newObj;
}
console.log(removeEmpty(data))
if you want to remove only those keys which has null or undefined then you can try this recursive function
const isObject = _ => _ instanceof Object && _.constructor.name == "Object"
const isEmpty = _ => isObject(_) ? !!!Object.values(_).length : false
const removeNullUndefined = (obj, level, recurse = true) => {
for (let key in obj) {
if (level) {
if ([null, undefined].indexOf(obj[key]) > -1)
delete obj[key]
else if (isObject(obj[key]))
obj[key] = removeNullUndefined(obj[key], level, false)
}
if (recurse) {
if (isEmpty(obj[key]))
delete obj[key]
--level
}
}
return obj
}
removeNullUndefined(YOUR_OBJECT, 2)
You can use lodash's _.transform() to recursively iterate a nested object, and build a new object without nil values (null or undefined), and empty objects / arrays.
const cleanObject = obj =>
_.transform(obj, (acc, v, k) => {
const val = _.isObject(v) ? cleanObject(v) : v // if current value is an object clean it
if(_.isNil(val) || _.isEmpty(val)) return // ignore null, undefined, or empty objects / arrays
acc[k] = val // assign to key
})
const data = {"say":{"value":null},"play":{"value":null},"dial":{"value":"7597365803","options":{"action":null,"answerOnBridge":false,"callerId":null,"hangupOnStar":false,"method":"GET","record":true,"recordingStatusCallback":"false","recordingStatusCallbackMethod":"POST","recordingStatusCallbackEvent":"completed","recordingTrack":"both","ringTone":null,"timeLimit":14400,"timeout":30,"trim":"do-not-trim","_id":"60cc1977c86fe21910ccbc85","__v":0}},"record":{"value":null},"gather":{"value":null},"pause":{"value":null},"redirect":{"value":null},"reject":{"options":null},"number":{},"user_id":"2","hangup":null,"_id":"60cc0c416349282be4ed2f16","__v":0}
const result = cleanObject(data)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

How map and filter over array of objects?

sorry guys but i have a dummy question..
i need to iterate objects from a json response and obtain only those how meet some conditions..
the response is like this:
result = [
{
"type": "EVENT",
"id": "001",
"tags": [
{
"id": "98765",
"name": "home"
}
]
},
{
"type": "EVENT",
"id": "002",
"tags": [
{
"id": "7654",
"name": "contact"
}
]
},
{
"type": "EVENT",
"id": "003",
"tags": []
}
]
I need to use only those whose type is 'event' and name properties in tags be home.
I tried map and filter, but I do not get the desired result
const eventType = result.filter(type => type.type == 'EVENT')
const nameFilter =
eventType.map(item => item.tags)
.filter(sub => sub.length) // remove empty []
.map(subarray => subarray.map(element => element.name )
.filter(element => element == 'home'));
result:
[
['home'], // dosen t work for me, because need all the object
[],
[]
]
You can use filter to loop thru the array. Use some to check if at least one element in the tags array has a property name with value of "home":
result.filter(o => o.type === "EVENT" && o.tags.some(s => s.name === "home"));
Demo:
let result = [{"type":"EVENT","id":"001","tags":[{"id":"98765","name":"home"}]},{"type":"EVENT","id":"002","tags":[{"id":"7654","name":"contact"}]},{"type":"EVENT","id":"003","tags":[]}];
let filtered = result.filter(o => o.type === "EVENT" && o.tags.some(s => s.name === "home"));
console.log( filtered );
You only need filter() and use find() or some() to check exist name in tags.
var filter = result.filter(c=> c.type == "EVENT" && c.tags.find(d=>d.name == 'home'));
var filter = result.filter(c=> c.type == "EVENT" && c.tags.some(d=>d.name == 'home'));
let result= [
{
"type": "EVENT",
"id": "001",
"tags": [
{
"id": "98765",
"name": "home"
}
]
},
{
"type": "EVENT",
"id": "002",
"tags": [
{
"id": "7654",
"name": "contact"
}
]
},
{
"type": "EVENT",
"id": "003",
"tags": []
}
]
var filter = result.filter(c=> c.type == "EVENT" && c.tags.find(d=>d.name == 'home'));
console.log(filter);
if you simply want to select elements from the root array then filter is the appropriate way to do.
if you want to also transform the result (say, select the TAG object), you may use flatMap
result.flatMap( e => (e.type == 'EVENT' && e.tags.some(t => t.name==='home')) ? e.tags : [] )

JSON Object get length

I have nested JSON which is as following:
var data = [
{
"id":"4",
"name":"2nd anniversary",
"date":"2015-12-17",
"location":"Mumbai",
"story_body":"Gzjjs jdk djks jdks jdkd jx djdb djd JD djbd djdj d",
"short_link":"izWfs",
"created_at":"2015-12-11 03:49:52",
"path":[
"\/SupportData\/ImpalzB2B\/uploads\/711453354154623.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/90294930451449759544217.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/471453355023537.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/90294930451449759544223.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/90294930451449759544179.jpg"
],
"update_type":"3"
},
{
"id":"7",
"name":"#1styearAnniversary",
"date":"2016-01-20",
"location":"Mumbai",
"story_body":"Bsjsj jdkdk djdkdk dkdkf kdkf dkfj fjfj fjfkjdd djkd",
"short_link":"FHXh0",
"created_at":"2016-01-20 23:10:54",
"path":"\/SupportData\/ImpalzB2B\/uploads\/11453356652175.jpg",
"update_type":"3"
},
{
"id":"19",
"name":"Product qetyfvhchv",
"description":"Cheers Vgdhvjd hugging",
"short_link":"jPE7G",
"created_at":"2016-01-18 05:03:46",
"path":"\/SupportData\/ImpalzB2B\/uploads\/90294930451453118625255.jpg",
"update_type":"4"
},
{
"id":"20",
"name":"F frfgcgj ggvvhv",
"description":" Vdhsj fgjjchk",
"short_link":"hMn8K",
"created_at":"2016-01-18 05:04:16",
"path":"\/SupportData\/ImpalzB2B\/uploads\/90294930451453118654785.jpg",
"update_type":"4"
},
{
"id":"25",
"name":"Gshsh djdj djdkd dkkd",
"description":"Bsjjd djjd djdirj dudir",
"short_link":"dhT6l",
"created_at":"2016-01-22 05:39:31",
"path":[
"\/SupportData\/ImpalzB2B\/uploads\/11453466369930.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/11453466369891.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/11453466369942.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/11453466369934.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/11453466369939.jpg"
],
"update_type":"4"
},
{
"id":"26",
"name":"For Healthy Breakfast, head over to our new restaurant in Andheri",
"description":"Delightful upma",
"short_link":"CG0i4",
"created_at":"2016-02-04 06:58:17",
"path":"\/SupportData\/ImpalzB2B\/uploads\/11454594295456.jpg",
"update_type":"4"
},
{
"id":"1",
"body":"#Awesome2Eat",
"votes":"28",
"update_type":"7",
"short_link":"GcKAe",
"created_at":"2016-02-04 01:28:53",
"name":"nehil"
},
{
"id":"10",
"body":"#Bouncy",
"votes":"1",
"update_type":"7",
"short_link":"JXUxz",
"created_at":"2016-02-04 00:12:52",
"name":"nehil"
},
{
"id":"11",
"body":"#Superman",
"votes":"0",
"update_type":"7",
"short_link":"4Keyd",
"created_at":"2016-02-04 01:17:36",
"name":"nehil"
}
]
How do I get lenght of path array from Object?
I tried which gives wrong length.
for (var key in data) {
if(data[key].update_type == '3'){
console.log(data[key].path.length); // 5 and 49 . It Should be 5 and 1
}
};
Also Is this the right way to get each element of Object? :
for (var key in data) {
console.log(data[key].id);
$.each(data[key].path, function (i, obj) {
console.log(obj);
});
};
Fiddle link: http://jsfiddle.net/Nehil/2ym3ffo0/
Because the type of value of data[key].path is not array (second instance), it is a String. And String also has the length attribute which gives the length of string.
make it
for (var key in data) {
if(data[key].update_type == '3')
{
if (typeof data[key].path == "string" )
{
console.log( 1 );
}
else
{
console.log(data[key].path.length); // 5 and 49 . It Should be 5 and 1
//to print all the elements on the console one by one
if ( data[key].path && data[key].path.length > 0 )
{
data[key].path.forEach( function(value){
console.log( value );
} );
}
}
}
}
You can use forEach loop:
The forEach() method executes a provided function once per array
element.
var data = [{
"id": "4",
"name": "2nd anniversary",
"date": "2015-12-17",
"location": "Mumbai",
"story_body": "Gzjjs jdk djks jdks jdkd jx djdb djd JD djbd djdj d",
"short_link": "izWfs",
"created_at": "2015-12-11 03:49:52",
"path": [
"\/SupportData\/ImpalzB2B\/uploads\/711453354154623.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/90294930451449759544217.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/471453355023537.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/90294930451449759544223.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/90294930451449759544179.jpg"
],
"update_type": "3"
}, {
"id": "7",
"name": "#1styearAnniversary",
"date": "2016-01-20",
"location": "Mumbai",
"story_body": "Bsjsj jdkdk djdkdk dkdkf kdkf dkfj fjfj fjfkjdd djkd",
"short_link": "FHXh0",
"created_at": "2016-01-20 23:10:54",
"path": "\/SupportData\/ImpalzB2B\/uploads\/11453356652175.jpg",
"update_type": "3"
}, {
"id": "19",
"name": "Product qetyfvhchv",
"description": "Cheers Vgdhvjd hugging",
"short_link": "jPE7G",
"created_at": "2016-01-18 05:03:46",
"path": "\/SupportData\/ImpalzB2B\/uploads\/90294930451453118625255.jpg",
"update_type": "4"
}, {
"id": "20",
"name": "F frfgcgj ggvvhv",
"description": " Vdhsj fgjjchk",
"short_link": "hMn8K",
"created_at": "2016-01-18 05:04:16",
"path": "\/SupportData\/ImpalzB2B\/uploads\/90294930451453118654785.jpg",
"update_type": "4"
}, {
"id": "25",
"name": "Gshsh djdj djdkd dkkd",
"description": "Bsjjd djjd djdirj dudir",
"short_link": "dhT6l",
"created_at": "2016-01-22 05:39:31",
"path": [
"\/SupportData\/ImpalzB2B\/uploads\/11453466369930.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/11453466369891.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/11453466369942.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/11453466369934.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/11453466369939.jpg"
],
"update_type": "4"
}, {
"id": "26",
"name": "For Healthy Breakfast, head over to our new restaurant in Andheri",
"description": "Delightful upma",
"short_link": "CG0i4",
"created_at": "2016-02-04 06:58:17",
"path": "\/SupportData\/ImpalzB2B\/uploads\/11454594295456.jpg",
"update_type": "4"
}, {
"id": "1",
"body": "#Awesome2Eat",
"votes": "28",
"update_type": "7",
"short_link": "GcKAe",
"created_at": "2016-02-04 01:28:53",
"name": "nehil"
}, {
"id": "10",
"body": "#Bouncy",
"votes": "1",
"update_type": "7",
"short_link": "JXUxz",
"created_at": "2016-02-04 00:12:52",
"name": "nehil"
}, {
"id": "11",
"body": "#Superman",
"votes": "0",
"update_type": "7",
"short_link": "4Keyd",
"created_at": "2016-02-04 01:17:36",
"name": "nehil"
}]
data.forEach((a) => { /*ES6 Arrow funtion. can use simple 'function(){}' too*/
if (typeof a.path == "string") {
console.log(1);
} else if(typeof a.path!=='undefined') {
console.log(a.path.length);
}else{
console.log(-1);
}
})
repeatedly throughout this answer I use this code:
var path = (item.path && typeof item.path == 'string' ? [item.path] : item.path) || [];
breaking it down, if item.path is truthy, if it's a string, set it to [item.path] (i.e. an array with a single element == item.path), othewise use item.path
if this results in a falsey value (item.path is undefined or null etc) set path = [] an empty array
Now path will always be an array, so .length/.forEach/$.each will work without any issue (except if item.path is something other that string/array/undefined/null of course)
as you already use jquery.each, you could do this
$.each(data, function(i, item) {
if (item.update_type == '3') {
var path = (item.path && typeof item.path == 'string' ? [item.path] : item.path) || [];
console.log(path.length);
}
});
and
$.each(data, function(i, item) {
console.log(item.id);
var path = (item.path && typeof item.path == 'string' ? [item.path] : item.path) || [];
$.each(path, function (i, obj) {
console.log(obj);
});
});
I prefer to use jquery as little as possible
data.forEach(function (item) {
if (item.update_type == '3') {
var path = (item.path && typeof item.path == 'string' ? [item.path] : item.path) || [];
console.log(path.length);
}
});
and
data.forEach(function (item) {
console.log(item.id);
var path = (item.path && typeof item.path == 'string' ? [item.path] : item.path) || [];
path.forEach(function (obj) {
console.log(obj);
});
});
to use forEach you may need this polyfill if you think you may need to support IE8 or less
This is my solution using UnderscoreJs:
_.each(data, function(item) {
if (item['update_type'] != '3') return;
var path = (_.isString(item.path) ? [item.path] : item.path) || [];
var pathCount = path.length;
// Log path count for item.
pathCount && console.log(pathCount);
// Or log path list for item.
pathCount && _.each(path, function(pathStr) { console.log(pathStr); });
});

Categories

Resources