Do not return null values in loop - javascript

How to return only the image_url when few image_url maybe null?
var lineItems = [
{
description: "Packaging",
image_url: null,
...
},
{
description: "T-Shirt",
image_url: <the-url-link>,
...
}
]
In react:
...
lineItems.map(function(line){
if (line.description !== "Packaging") {
var img = line.image_url;
}
console.log(img);
});
...
I keep getting null along with the web links in the console. How to grab only the image_url that has the links. "Packaging" will never have an image_url link; it'll always be null.

You can simply use a filter here to do that for you.
const nonNulls = lineItems.filter(item => item.image_url !== null);
This will filter out all the non-null values into a variable.

var data = [
{
url: null
},
{
url: null
},
{
url: '123'
},
{
url: null
}
]
console.log(
data.filter(function (a) {
return a.url != null
}).map(function (a) {
return a.url
})
)

Related

Getting last appearance of a deeply nested value by specified property

I've got this object as example:
const obj = {
group: {
data: {
data: [
{
id: null,
value: 'someValue',
data: 'someData'
}
]
}
}
};
My goal is to get a value by propery name.
In this case I would like to get
the value of the data propery, but the last appearance of it.
Meaning the expected output is:
someData
However, I'm using this recursive function to retreive it:
const findVal = (obj, propertyToExtract) => {
if (obj && obj[propertyToExtract]) return obj[propertyToExtract];
for (let key in obj) {
if (typeof obj[key] === 'object') {
const value = findVal(obj[key], propertyToExtract);
if (value) return value;
}
}
return false;
};
Which gives me the first appearance of data, meaning:
data: [
{
value: 'someValue',
data: 'someData'
}
]
How can I get the wanted result?
one way can be to recursively flat the object and just get the wanted index (here data)
const obj = {
group: {
data: {
data: [
{
id: null,
value: 'someValue',
data: 'someData'
}
]
}
}
};
function deepFlat(obj) {
let flatObj = {};
flat(obj,flatObj);
console.log(flatObj);
return flatObj;
}
function flat(toFlat, flatObj) {
Object.entries(toFlat).forEach(elem => {
if (elem[1] && typeof elem[1] === 'object') {
flat(elem[1], flatObj);
} else {
flatObj[elem[0]] = elem[1];
}
});
}
let result = deepFlat(obj);
console.log(result['data']);

How to check if boolean is passed as string?

So in below code if i pass ancillaryProductInd as boolean code works, but when I pass it as a string, it does not work. In my understanding the below code should only work when I pass "false" string value and throw error on boolean. Any idea what is the issue here ?
main.ts
request
var rxInfos = [{
"ancillaryProductInd": "false",
"indexID": "eyJrZXkiOiIEOHdpNUpNWmR3PT0ifQ=="
}]
function subQuestionsHandler(rxInfos, data) {
const subQuestionArray = [];
rxInfos.forEach((rxInfo) => {
const subQuestion = {
question: []
};
if (rxInfo.ancillaryProductInd !== undefined && rxInfo.ancillaryProductInd === "false") {
subQuestion.question = data;
subQuestionArray.push(subQuestion);
}
});
return subQuestionArray;
}
subQuestionsHandler(rxInfos, [{
some data
}]);
Your example code works as expected with a string value "false" and doesnt run the if block when a boolean is used. See my example:
var rxInfos = [
{
ancillaryProductInd: "false",
indexID: "eyJrZXkiOiIEOHdpNUpNWmR3PT0ifQ=="
},
{
ancillaryProductInd: false,
indexID: "eyJrZXkiOiIEOHdpNUpNWmR3PT0ifQ=="
}
];
function subQuestionsHandler(rxInfos, data) {
const subQuestionArray = [];
rxInfos.forEach(rxInfo => {
const subQuestion = {
question: []
};
if (
rxInfo.ancillaryProductInd !== undefined &&
rxInfo.ancillaryProductInd === "false"
) {
console.log("no error");
subQuestion.question = data;
subQuestionArray.push(subQuestion);
} else {
console.log("throw error");
}
});
return subQuestionArray;
}
subQuestionsHandler(rxInfos, [
{
test: ""
}
]);

Writing a recursive javascript algorithm to find a specific object type

Essentially, I'm testing a hierarcy treeview dataset to see if there exists any object which is considered a Host node; meaning, it simply has properties HostID and HostName.
If I find just one Host node, I return true - and I'm done.
However, I'm not getting an accurate true/false return value in this recursive routine below. i.e. I get an inaccurate false return values sometimes.
hasChildHosts_2(tree: any) {
if (tree.subs !== null && tree.subs.length > 0) {
for (var i = 0; i < tree.subs.length; i++) {
if (tree.subs[i].HostID != null && tree.subs[i].HostName != null) {
return true;
}
if (tree.subs[i].subs !== undefined) {
this.hasChildHosts_2(tree.subs[i]);
}
}
return false;
} else {
return false;
}
}
a small sample set as follows: a Location node contains a subs array - which contains a Location node and two Host nodes. And of course I always know a Location by the LocationName prop and a Host by the HostID prop :
{ "UID":2,"GUID":"","LocationName":"Bergen County","ParentLocation":null, "subs":[ {"UID":42,"GUID":"","LocationName":"yy","Description":"","subs":[ {"UID":3,"GUID":"","LocationName":"Essex County","ParentLocation":null} {"HostID":100,"HostName":"MYHOST100","HostIP":"10.1.1.12"},
{"HostID":200,"HostName":"MYHOST200","HostIP":"10.1.1.19"} ] ] } }
Please review for accuracy. Feedback is appreciated.
I've implemented your code on a sample codepen. As pointed on comments, you need to return the result of the recursive function. Furthemore, the tree is an invalid JSON, I've fixed it:
var globalTree = {
UID: 2,
GUID: "",
LocationName: "Bergen County",
ParentLocation: null,
subs: [{
UID: 42,
GUID: "",
LocationName: "yy",
Description: "",
subs: [{
UID: 3,
GUID: "",
LocationName: "Essex County",
ParentLocation: null
},
{
HostID: 100,
HostName: "MYHOST100",
HostIP: "10.1.1.12"
},
{
HostID: 200,
HostName: "MYHOST200",
HostIP: "10.1.1.19"
}
]
}]
};
var hasChildHosts_2 = function(tree) {
if (tree.subs !== null && tree.subs.length > 0) {
for (var i = 0; i < tree.subs.length; i++) {
if (tree.subs[i].HostID != null && tree.subs[i].HostName != null) {
return true;
}
if (tree.subs[i].subs !== undefined) {
return hasChildHosts_2(tree.subs[i]);
}
}
return false;
} else {
return false;
}
};
console.log("result: " + hasChildHosts_2(globalTree));
Can't you simply check each item and recurse on subs if it's an array:
let obj = {"UID":2,"GUID":"","LocationName":"Bergen County","ParentLocation":null,"subs":[{"UID":42,"GUID":"","LocationName":"yy","Description":"","subs":[{"UID":3,"GUID":"","LocationName":"Essex County","ParentLocation":null},{"HostID":100,"HostName":"MYHOST00","HostIP":"10.1.1.12"},{"HostID":200,"HostName":"MYHOST00","HostIP":"10.1.1.19"}]}]}
let obj_no_host = {"UID":2,"GUID":"","LocationName":"Bergen County","ParentLocation":null,"subs":[{"UID":42,"GUID":"","LocationName":"yy","Description":"","subs":[{"UID":3,"GUID":"","LocationName":"Essex County","ParentLocation":null},{"HostID":100},{"HostID":200}]}]}
function test(o){
for (item of o) {
if (item.HostName !== undefined && item.HostIP !== undefined) return true
if (Array.isArray(item.subs)) return test(item.subs)
}
return false
}
console.log("With host -- ", test([obj]))
console.log("Without host -- ", test([obj_no_host]))

jQuery how to $.map over a dynamic length of an array

I have the following:
transformResult: function(response) {
if (response && response.buckets && response.buckets[0] && response.buckets[0].documents) {
return {
suggestions: $.map(response.buckets[0].documents, function(dataItem) {
return { value: dataItem._id, data: {
key: response.buckets[0].key,
url: dataItem.url
}
};
})
};
}
I'm using response.buckets[0] to ensure at least one bucket exists in the array. There can be 0 or 1+ buckets. The problem is, now the suggestions are just returning for the first bucket w [0] in response.buckets[0].documents
How can I get the suggestions to return for 0 or more $.map(response.buckets[0].documents?
Update
transformResult: function(response) {
var suggestions = {
suggestions: {}
};
if(!response || !response.buckets) {
return suggestions;
}
for(var i=0;i<response.buckets.length;i++) {
var bucket = response.buckets[i];
if(!!bucket.documents) {
suggestions.concat($.map(bucket.documents, function(item) {
return {
value: item._id,
data: {
key: bucket.key,
url: item.url
}
}
}));
};
}
return suggestions;
},
This is now erroring with: Uncaught TypeError: suggestions.concat is not a function
If you run a for loop on the buckets-array and inside the for run the map function on each element you should achieve what you are after.
var suggestions = [];
if(!response || !response.buckets) {
return { suggestions: suggestions };
}
for(var i=0;i<response.buckets.length;i++) {
var bucket = response.buckets[i];
if(!!bucket.documents) {
suggestions.concat($.map(bucket.documents, function(item) {
return {
value: item._id,
data: {
key: bucket.key,
url: item.url
}
};
}));
}
}
return { suggestions: suggestions };
If there are 0 buckets, the for-loop will not loop at all and the suggestions array will be of 0 length.
I'm not entirely sure wether I got your intention and data-structure right, but I think you're looking for this:
transformResult: function(response) {
//seems that $.map() doesn't handle null-values :(
//so I have to take care of this
var emptyArray = [];
return {
suggestions: $.map(response && response.buckets || emptyArray, function(bucket){
//jQuerys map-implementation is actually more like a fmap.
//so this doesn't return an Array of Arrays, but one flat Array instead
return $.map(bucket.documents || emptyArray, function(document){
return {
value: document._id,
data: {
key: bucket.key,
url: document.url
}
}
});
})
}
}

promise mapping array of objects with array values

Kind of lost when iterating over promises, im trying to transform this:
[{
' site' : ['url', 'url', 'url']
},
{
' site' : ['url', 'url', 'url']
}]
so that it becomes:
[{
'site' : [{ 'url' : result_of_function }, { 'url' : result_of_function }, { 'url' : result_of_function }]
},
{
'site' : [{ 'url' : result_of_function }, { 'url' : result_of_function }, { 'url' : result_of_function }]
}]
So far I created the function below, but for some reason checkBranding is not called.
function searchPageArray(brand, siteObjArr) {
return Promise.map(siteObjArr, function(sitesObj){
var k = Object.keys(sitesObj)[0]
var urlArr = sitesObj[k];
return Promise.map(urlArr, function(url){
return searchPage(url).then(function(html){
var tempObj = {}
tempObj[url] = checkBranding(url, html, brand)
return tempObj
})
})
return sitesObj;
})
}
Thanks for the help!
You can use bluebird.js's props() method.
// You must use bluebird to achieve this
var Promise = require('bluebird');
function searchPageArray(brand, siteObjArr) {
return Promise.map(siteObjArr, function (sitesObj) {
var k = Object.keys(sitesObj)[0]
var urlArr = sitesObj[k];
return Promise.map(urlArr, function (url) {
return searchPage(url)
.then(function (html) {
// Use promise.props(). It resolves all properties of a
// object before returning. If there are any properties that
// arent promises they are returned as normal.
return Promise.props({
url: checkBranding(url, html, brand) // Assuming checkBranding() returns a promise.
});
});
});
return sitesObj;
});
}

Categories