Break Nested some or map JavaScript - javascript

PC = {a:{ID: "abc",options:{x1:"100", x2:"200"}},b:{ID: "d",options:{x2:"100", x3:"200"}}}
pro = {
"pro": [
{
"pID": "abc",
"attributes": {
"xyz": [
"1",
"2",
"3"
],
"foo": "フルプレミアム"
}
}
]
}
functionX() {
let isND = true;
if (pro === null || pro === [] || pro.length === 0) {
return isND;
} else if (pro.length > 0) {
some(PC, (p) => {
some(p.options, (o, k) => {
some(pro, (item) => {
if (p.ID === item.pID && k === 'xyz') {
if (item.attributes[k] !== []) {
isND = false;
}
} else if (p.ID === item.pID && k !== 'xyz') {
if (item.attributes[k] !== '') {
isND = false;
}
}
});
});
});
}
return isND;
}
I have to iterate through 3 different collections to check my condition and return a value. I am trying to exit the nested some or map if one of my if- else conditions satisfy. I tried passing return true after isND = false but doesn't work. Can someone help resolve this.

Array.prototype.some() will exit early if any of the callbacks return true so you could return the result that way.
It's not very clear but it seems you want to use this "early exit" feature while returning the inverse. How about something like this...
// ignoring "if (pro === null || pro === [] || pro.length === 0)" for this example
// return the inverse
return !Object.values(PC).some(({ ID, options }) => {
return Object.entries(options).some(([k, o]) => {
// here "k" is one of your "x1", "x2", etc keys
// and "o" is the corresponding value
return pro.pro.some(item => {
// return "true" if any of your "conditions" are met
})
})
})

return Object.values(PC).some(({ ID, options }) => {
return Object.entries(options).some(([k]) => {
return (pro.pro).some((item) => {
if (condition) {
if (condition) {
return false;
}
return true;
} else if (condition) {
if (condition) {
return false;
}
return true;
}
return null;
});
});
});
// Haven't returned the inverse of outer function

Related

How to make search case insensitive in Angular

I have a list of data names and I want to search through it. It should give result irrespective of the case.
this is what I have:
public groups = [{ name: '"Grx-1"', selected: false }, { name: '"Grx-man-2"', selected: false }, { name: '"Grx-up-3"', selected: false }];
queryGroups(groupName) {
this.groups = this.totalGroupsList.filter((group) => {
if (group.userId.includes(groupName) || group.dps.includes(groupName) || group.sourceType.includes(groupName)) {
return true;
} else {
let isRole = false;
group.role.forEach((role) => {
if (role.name.includes(groupName)) {
isRole = true;
return;
}
});
if (isRole === false) {
return false;
} else {
return true;
}
}
});
}
If I search for "Grx" I get all the results. I want that if I search for "grx" i should get all the results.
You can use toLowerCase()
role.name.toLowerCase().includes(groupName.toLowerCase())
You must use more than one search method :
queryGroups(groupName: string) {
this.groups = this.totalGroupsList.filter((group) => {
let isExist = this.searchFunc(groupName, group.userId)
|| this.searchFunc(groupName, group.dps)
|| this.searchFunc(groupName, group.sourceType)
if (isExist) {
return true;
} else {
let isRole = false;
group.role.forEach((role) => {
if (this.searchFunc(groupName, role.name)) {
isRole = true;
break;
}
});
return isRole !== false;
}
});
}
private searchFunc(searchKey, searchTarget): boolean {
if(!searchKey) {
return false;
}
return (searchTarget.toLocaleUpperCase().includes(searchKey.toLocaleUpperCase())) ||
(searchTarget.toUpperCase().includes(searchKey.toUpperCase())) ||
(searchTarget.includes(searchKey.toLocaleUpperCase())) ||
(searchTarget.includes(searchKey.toUpperCase())) ||
(searchTarget.toLocaleUpperCase().includes(searchKey)) ||
(searchTarget.toUpperCase().includes(searchKey)) ||
(searchTarget.includes(searchKey))
}

Convert repeating "if" to "loop" instead (javascript)

I have JSON data coming with values like: status -> pla -> wea -> wea_0 -> stat
They're a series of wea_0, wea_1, wea_2,... inside pla
And I try to check if stat from them is acte
Here's my code:
if (status.pla.wea.wea_0.stat === 'acte') {
save_acte();
} else if (status.pla.wea.wea_1.stat === 'acte') {
save_acte();
} else if (status.pla.wea.wea_2.stat === 'acte') {
save_acte();
} else if (status.pla.wea.wea_3.stat === 'acte') {
save_acte();
} else if (status.pla.wea.wea_4.stat === 'acte') {
save_acte();
} else if (status.pla.wea.wea_5.stat === 'acte') {
save_acte();
} else if (status.pla.wea.wea_6.stat === 'acte') {
save_acte();
}
Please help me to turn this to loop or for instead.
Access the wea_x as properties with dynamic name:
for (let i = 0; i < 7; i++) {
if (status.pla.wea[`wea_${i}`].stat === "acte") {
save_acte();
}
}
You can use an array with all the possible indices of wea_* in it and iterate over that, checking each wea_* entry in turn. For example:
const status = {
pla: {
wea: {
wea_0: {
stat: "blah"
},
wea_1: {
stat: "blah"
},
wea_2: {
stat: "acte"
},
wea_3: {
stat: "blah"
}
}
}
};
function save_acte(i) {
console.log('saved acte ' + i);
}
[0,1,2,3].forEach(i => status.pla.wea['wea_' + i].stat === 'acte' ? save_acte(i) : '');
// or, if you're not using IE
[...Array(4).keys()].forEach(i => status.pla.wea['wea_' + i].stat === 'acte' ? save_acte(i) : '');

Recursion mess while checking object properties

I have an object which could be nested as deep as possible. I'm trying to determine if object's property ready has at least one false value. If so the checkForFalse function should return false. I got confused while using recursion to solve this problem. What recursion call should return to make this code work? Or I'm completely wrong and missing something?
var obj = {
"currentServiceContractId": {
"ready": true,
"customerPersonId": {
"ready": false
}
},
"siteId": {
"ready": true
},
"districtId": {},
"localityId": {
"ready": true
},
"streetId": {
"ready": true
}
};
function checkForFalse(mainObj) {
let ans = _.find(mainObj || obj, (val) => {
if (_.keys(val).length > 1) {
let readyObj = _.pick(val, 'ready');
return checkForFalse(readyObj);
} else {
return _.get(val, 'ready') === false;
}
});
return _.isEmpty(ans);
}
console.log(checkForFalse(obj));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
This solution uses _.every() recursively to search for ready: false. The _.every() method will return immediately when the callback returns false:
function checkForAllReady(mainObj) {
return _.every(mainObj, (value, key) => {
if(key === 'ready' && value === false) {
return false;
}
if(_.isObject(value)) {
return checkForAllReady(value);
}
return true;
});
}
const obj = {"currentServiceContractId":{"ready":true,"customerPersonId":{"ready":true}},"siteId":{"ready":true},"districtId":{},"localityId":{"ready":true},"streetId":{"ready":true}};
console.log(checkForAllReady(obj));
const objWithFalse = _.merge({}, obj, { "streetId":{"ready":false} })
console.log(checkForAllReady(objWithFalse));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>

JavaScript - Performing a recursive search, value not being retained

I am trying to perform a search on an array of vehicles to see if any match the "Make" of "BMW".
Problem: While matches are found and result is given the value true, that value is lost as the function continues the loop. I thought I would be able to break out of the function, anytime a true value is found. The break is not working.
If I cannot break out of the function and must continue looping thru the remainder of that parent node's properties, how can I retain the true value, as once true is found, I am basically done with this node (vehicle).
Thanks
Here is a truncated look at my node tree:
[
{
"title": "2008 BMW 650",
"price": "30,995.00",
"type": "Coupes",
"details" : [{.....}],
"features" : [
{ ..... },
{ "name": "Make", "value": "BMW" },
{ ..... }
]
},
{ ..... }
]
let isPresent = recursiveFilterSearch(node, "Make", "BMW")
function recursiveFilterSearch(node, filterObj, filterValue) {
let result;
for (var key in node) {
// if the any node name & value matches, return true (on this vehicle)
if (node.name !== undefined) {
if (node.name === filterObj && node.value === filterValue) {
result = true;
break; // <-- not doing what I thought it would do
}
}
// if this node property is an array recursively loop thru the array's properties
if (result !== true && Object.prototype.hasOwnProperty.call(node, key)) {
var isArray = Object.prototype.toString.call(node[key]) === '[object Array]';
if (isArray) {
var childrenNode = node[key];
childrenNode.map(function (childNode) {
recursiveFilterSearch(childNode, filterObj, filterValue);
});
}
}
}
return result;
}
Struggled hard on this one, no help from those far smarter than I.
I hope this helps others.
I purposely did not do a search by features (as plalx above suggested), because I want to re-use this code on products that may not have a feature section. One can use this for any product, ie. from cars to shoes to TVs. The property names do not matter.
Make note I purposely lower-cased the respective variables, just to play it safe, as well as using indexOf on the value as my client has such values as "Automatic" & "6-speed Automatic", so index will pick up both when a search is done on "automatic".
collection-filter.js (javascript file)
function recursiveFilterSearch(node, filterObj, filterValue) {
let result = false;
for (const prop in node) {
if (node !== undefined) {
if (node.value !== undefined) {
node.name = (node.name).toLowerCase();
node.value = (node.value).toLowerCase();
if (node.name === filterObj && (node.value).indexOf(filterValue) > -1) {
result = true;
}
}
if (typeof(node[prop]) === 'object') {
recursiveFilterSearch(node[prop], filterObj, filterValue);
}
if (result) {
break;
}
}
}
return result;
}
module.exports = {
filterCollection(coll2Filter, filterName, filterValue) {
const results = [];
coll2Filter.map((node) => {
const isMatch = (recursiveFilterSearch(node, filterName.toLowerCase(), filterValue.toLowerCase()));
if (isMatch) {
results.push(node);
}
});
return results;
}
};
}
Inventory.js: (React.js file using alt flux)
import CollectionFilter from '../../components/forms/helpers/collection-filter.js';
render() {
if (!this.props.items) return <div>Loading ...</div>;
const products = this.props.items;
const result = CollectionFilter.filterCollection(products, 'Trans', 'Automatic');
return (
<div>{ result }</div>
)
.....
You do not assign the return value of your recursive call:
if (result !== true && Object.prototype.hasOwnProperty.call(node, key)) {
var isArray = Object.prototype.toString.call(node[key]) === '[object Array]';
if (isArray) {
var childrenNode = node[key];
childrenNode.map(function (childNode) {
// assign recursive result
result = recursiveFilterSearch(childNode, filterObj, filterValue);
});
}
}
As a side note:
Such a generic search functionality will work but if you are developing new functionality and you have full control over the json structure keep things like 'searchability' in mind.
Were the structure like:
{
features: {
make: "Opel",
ft2: ""
}
}
You could loop all object and search like:
if (car.features.make == "Opel") {
// found in one liner
}

JS find key value pair in encapsulated object

I have a big problem and I need your help.
I have a object like this:
{
folder1: {
folderid: 1,
files: {
name: "yeah.txt"
},
folder2: {
folderid: 2
folder3: {
folderid: 3
}
}
},
folder4: {
folderid: 4
}
}
and I want to search for the key "folderid = 3" and find the object.
How can I do this in JavaScript?
Kind regards and thanks for your help
I came to a more generalised solution, that supports multiple properties check:
function search(obj, properties){
if(Object.keys(properties).every(function(key){
return obj[key] === properties[key];
})) {
return obj;
} else {
Object.keys(obj).forEach(function(key){
var child = obj[key];
if(child !== null && typeof child === 'object'){
return search(child, properties);
}
});
return false;
}
}
demo: http://jsfiddle.net/dzs1orbw/
You can use a DSF algorithm to do this: http://jsfiddle.net/L5b07bt6/
var obj = {
folder1: {
folderid: 1,
files: {
name: "yeah.txt"
},
folder2: {
folderid: 2,
folder3: {
folderid: 3,
caption: "I got it!"
}
}
},
folder4: {
folderid: 4
}
};
function find(root, id) {
if (root.folderid == id) return root;
if (typeof root !== 'object') return null;
var key, val;
for (key in root) {
val = find(root[key], id);
if (val != null) return val;
}
return null;
}
var result = find(obj, 3);
if (!result) alert("Not found!");
else alert("Found: " + result.caption);
and here another one:
function findByKey (object, searchKey){
if(typeof object !== 'object'){
return false;
}
for(var key in object){
if(object[key] === searchKey){
return object;
} else {
if(typeof (object[key] === 'object')){
var result = findByKey(object[key], searchKey);
if(result){
return result;
}
}
}
}
}
http://jsfiddle.net/mattposch/ebmd8xtk/

Categories

Resources