My question might be a little unclear. Same questions were also asked before but I couldn't figure out how to solve mine by reading them. I need more clear guidance:
I have already created three functions to check colors. (I don't have issues with them. I am not including them here because of the size.)
Lets assume we have three working functions like that:
function checkHex(input) {
// returns boolean value if input is hex color
}
checkHex("#1234a6"); // returns true
function checkRGB(input) {
// returns boolean value if input is RGB color
}
checkRGB("rgb(255, 255, 112)"); // returns true
function checkHSL(input) {
// returns boolean value if input is hsl color
}
checkHSL("hsl(122, 1, 1)"); // returns true
I am having 4th function (checkColor) which has mixed color values to check:
function checkColor(input) {
// returns boolean value if input belong to right color value
}
checkColor("#ccccff"); // should return true
checkColor("rgb(255,255,200)"); // should return true
checkColor("hls(46,0.66,0.21)"); // should return true
QUESTION: Do I have to include all three functions(checkHex,checkRGB,checkHSL) into the 4th one (checkColor)? How do I do that. I researched about that and tried couple ways to solve but I couldn't.
I am trying to do it without using RegExp. I am new to programming, never merged multiple functions before.
Any additional resource you can share with me about "combining multiple functions" will help me a lot too.
Thank you for your time and effort in advance !
The first 3 functions you built are often called predicates. There are a bunch of great ways to group predicates but #FelixKling mentions the simplest in the comments. You could also create functions specifically for this purpose.
// composition function
const any = (...predicates) => subject => predicates.reduce((state, predicate) => (state || predicate(subject)), false);
// predicates
const biggerThan5 = x => x>5;
const isOdd = x => !!(x % 2);
// results and usage
console.log(any(biggerThan5, isOdd)(10)); // true
console.log(any(biggerThan5, isOdd)(2)); // false
You shouldn't include functions into other functions, you just can use them inside of other ones.
For example:
function checkColor(input) {
var isHex = checkHex(input), //store the result of function
isRGB = checkRGB(input), //store the result of function
isHLS = checkHSL(input); //store the result of function
return isHex || isRGB || isHLS; //returns true if one of the options is true.
}
function checkHex(input) {
// returns boolean value if input is hex color
}
function checkRGB(input) {
// returns boolean value if input is RGB color
}
function checkHSL(input) {
// returns boolean value if input is hsl color
}
Related
I have a search function that takes input/query text from a search bar. I want it to work for multiple search terms like "javascript react" or with more or less search terms. The input is saved in an array in state ("query") and compares to an object "workitem" and its property "description".
Let say:
workitem.description.includes(this.state.query)
where
this.state.query // = ["react", "javacript"]
Above will only work for certain situations. I want to see if the array/object includes ANY elements of the state. How to do it?
// if needed, do a
// if (!workitem.description || !this.state.query) {
// return false;
// }
Considering description is an array:
return workitem.description.some(desc => this.state.query.indexOf(desc) >= 0)
Considering description is a string:
return workitem.description
.split(' ')
.some(desc => state.query.indexOf(desc) >= 0);
How about this:
workitem.description.split(' ').some(str => this.state.query.includes(str))
I'm a backend dev moved recently onto js side. I was going through a tutorial and came across the below piece of code.
clickCreate: function(component, event, helper) {
var validExpense = component.find('expenseform').reduce(function (validSoFar, inputCmp) {
// Displays error messages for invalid fields
inputCmp.showHelpMessageIfInvalid();
return validSoFar && inputCmp.get('v.validity').valid;
}, true);
// If we pass error checking, do some real work
if(validExpense){
// Create the new expense
var newExpense = component.get("v.newExpense");
console.log("Create expense: " + JSON.stringify(newExpense));
helper.createExpense(component, newExpense);
}
}
Here I tried to understand a lot on what's happening, there is something called reduce and another thing named validSoFar. I'm unable to understand what's happening under the hood. :-(
I do get the regular loops stuff as done in Java.
Can someone please shower some light on what's happening here. I should be using this a lot in my regular work.
Thanks
The reduce function here is iterating through each input component of the expense form and incrementally mapping to a boolean. If you have say three inputs each with a true validity, the reduce function would return:
true && true where the first true is the initial value passed into reduce.
true && true and where the first true here is the result of the previous result.
true && true
At the end of the reduction, you're left with a single boolean representing the validity of the entire, where by that if just a single input component's validity is false, the entire reduction will amount to false. This is because validSoFar keeps track of the overall validity and is mutated by returning the compound of the whether the form is valid so far and the validity of the current input in iteration.
This is a reasonable equivalent:
var validExpense = true;
var inputCmps = component.find('expenseform')
for (var i = 0; i < inputCmps.length; i++) {
// Displays error messages for invalid fields
inputCmp.showHelpMessageIfInvalid();
if (!inputCmp.get('v.validity').valid) {
validExpense = false;
}
}
// Now we can use validExpense
This is a somewhat strange use of reduce, to be honest, because it does more than simply reducing a list to a single value. It also produces side effects (presumably) in the call to showHelpMessageIfInvalid().
The idea of reduce is simple. Given a list of values that you want to fold down one at a time into a single value (of the same or any other type), you supply a function that takes the current folded value and the next list value and returns a new folded value, and you supply an initial folded value, and reduce combines them by calling the function with each successive list value and the current folded value.
So, for instance,
var items = [
{name: 'foo', price: 7, quantity: 3},
{name: 'bar', price: 5, quantity: 5},
{name: 'baz', price: 19, quantity: 1}
]
const totalPrice = items.reduce(
(total, item) => total + item.price * item.quantity, // folding function
0 // initial value
); //=> 65
It does not make sense to use reduce there and have side effects in the reduce. Better use Array.prototype.filter to get all invalid expense items.
Then use Array.prototype.forEach to produce side effect(s) for each invalid item. You can then check the length of invalid expense items array to see it your input was valid:
function(component, event, helper) {
var invalidExpenses = component.find('expenseform').filter(
function(ex){
//return not valid (!valid)
return !ex.get('v.validity').valid
}
);
invalidExpenses.forEach(
//use forEach if you need a side effect for each thing
function(ex){
ex.showHelpMessageIfInvalid();
}
);
// If we pass error checking, do some real work
if(invalidExpenses.length===0){//no invalid expense items
// Create the new expense
var newExpense = component.get("v.newExpense");
console.log("Create expense: " + JSON.stringify(newExpense));
helper.createExpense(component, newExpense);
}
}
The mdn documentation for Array.prototype.reduce has a good description and examples on how to use it.
It should take an array of things and return one other thing (can be different type of thing). But you won't find any examples there where side effects are initiated in the reducer function.
PS: I have already searched the forums and have seen the relevant posts for this wherein the same post exists but I am not able to resolve my issue with those solutions.
I have 2 json objects
var json1 = [{uid:"111", addrs:"abc", tab:"tab1"},{uid:"222", addrs:"def", tab:"tab2"}];
var json2 = [{id:"tab1"},{id:"new"}];
I want to compare both these and check if the id element in json2 is present in json1 by comparing to its tab key. If not then set some boolean to false. ie by comparing id:"tab1" in json2 to tab:"tab1 in json1 .
I tried using below solutions as suggested by various posts:
var o1 = json1;
var o2 = json2;
var set= false;
for (var p in o1) {
if (o1.hasOwnProperty(p)) {
if (o1[p].tab!== o2[p].id) {
set= true;
}
}
}
for (var p in o2) {
if (o2.hasOwnProperty(p)) {
if (o1[p].tab!== o2[p].id) {
set= true;
}
}
}
Also tried with underscore as:
_.each(json1, function(one) {
_.each(json2, function(two) {
if (one.tab!== two.id) {
set= true;
}
});
});
Both of them fail for some test case or other.
Can anyone tell any other better method or outline the issues above.
Don't call them JSON because they are JavaScript arrays. Read What is JSON.
To solve the problem, you may loop over second array and then in the iteration check if none of the objects in the first array matched the criteria. If so, set the result to true.
const obj1 = [{uid:"111", addrs:"abc", tab:"tab1"},{uid:"222",addrs:"def", tab:"tab2"}];
const obj2 = [{id:"tab1"},{id:"new"}];
let result = false;
for (let {id} of obj2) {
if (!obj1.some(i => i.tab === id)) {
result = true;
break;
}
}
console.log(result);
Unfortunately, searching the forums and reading the relevant posts is not going to replace THINKING. Step away from your computer, and write down, on a piece of paper, exactly what the problem is and how you plan to solve it. For example:
Calculate for each object in an array whether some object in another array has a tab property whose value is the same as the first object's id property.
There are many ways to do this. The first way involves using array functions like map (corresponding to the "calculate for each" in the question, and some (corresponding to the "some" in the question). To make it easier, and try to avoid confusing ourselves, we'll do it step by step.
function calculateMatch(obj2) {
return obj2.map(doesSomeElementInObj1Match);
}
That's it. Your program is finished. You don't even need to test it, because it's obviously right.
But wait. How are you supposed to know about these array functions like map and some? By reading the documentation. No one help you with that. You have to do it yourself. You have to do it in advance as part of your learning process. You can't do it at the moment you need it, because you won't know what you don't know!
If it's easier for you to understand, and you're just getting started with functions, you may want to write this as
obj2.map(obj1Element => doesSomeElementInObj1Match(obj1Element))
or, if you're still not up to speed on arrow functions, then
obj2.map(function(obj1Element) { return doesSomeElementInObj1Match(obj1Element); })
The only thing left to do is to write doesSomeElementInObj2Match. For testing purposes, we can make one that always returns true:
function doesSomeElementInObj2Match() { return true; }
But eventually we will have to write it. Remember the part of our English description of the problem that's relevant here:
some object in another array has a tab property whose value is the same as the first object's id property.
When working with JS arrays, for "some" we have the some function. So, following the same top-down approach, we are going to write (assuming we know what the ID is):
In the same way as above, we can write this as
function doesSomeElementInObj2Match(id) {
obj2.some(obj2Element => tabFieldMatches(obj2Element, id))
}
or
obj2.some(function(obj2Element) { return tabFieldMatches(obj2Element, id); })
Here, tabFieldMatches is nothing more than checking to make sure obj2Element.tab and id are identical.
We're almost done! but we still have to write hasMatchingTabField. That's quite easy, it turns out:
function hasMatchingTabField(e2, id) { return e2.tab === id; }
In the following, to save space, we will write e1 for obj1Element and e2 for obj2Element, and stick with the arrow functions. This completes our first solution. We have
const tabFieldMatches = (tab, id) { return tab === id; }
const hasMatchingTabField = (obj, id) => obj.some(e => tabFieldMatches(e.tab, id);
const findMatches = obj => obj.some(e => hasMatchingTabField(e1, obj.id));
And we call this using findMatches(obj1).
Old-fashioned array
But perhaps all these maps and somes are a little too much for you at this point. What ever happened to good old-fashioned for-loops? Yes, we can write things this way, and some people might prefer that alternative.
top: for (e1 of obj1) {
for (e2 of (obj2) {
if (e1.id === e2.tab) {
console.log("found match");
break top;
}
}
console.log("didn't find match);
}
But some people are sure to complain about the non-standard use of break here. Or, we might want to end up with an array of boolean parallel to the input array. In that case, we have to be careful about remembering what matched, at what level.
const matched = [];
for (e1 of obj1) {
let match = false;
for (e2 of obj2) {
if (e1.id === e2.tab) match = true;
}
matched.push(match);
}
We can clean this up and optimize it bit, but that's the basic idea. Notice that we have to reset match each time through the loop over the first object.
I am programming in Polymer 1.0 and am trying to create an IF function to change the value of a property. My function is the following:
_searchButton: function(selectednamedropdown, selectedtypedropdown){
if (selectednamedropdown=="no_name_selected" && selectedtypedropdown=="no_type_selected"){
this.searchUsagesBtn = true
} else{
this.searchUsagesBtn = false
}
}
In my mind when selectednamedropdown is equal to "no_name_selected" and selectedtypedropdown is equal to "no_type_selected" the function should set searchUsagesBtn to true and when they are not these values, false.
However, the function does not ever seem to be returning true even when these conditions are met. Any ideas why this might be? Thanks for all help
When I run your function like this:
let searchUsagesBtn;
function search(selectednamedropdown, selectedtypedropdown) {
if (
selectednamedropdown === "no_name_selected" &&
selectedtypedropdown === "no_type_selected"
) {
searchUsagesBtn = true;
} else {
searchUsagesBtn = false;
}
}
search("no_name_selected", "no_type_selected");
console.log("button: ", searchUsagesBtn);
I get button: true in console log. So maybe your inputs in this function are not a strings.
The issue was around how JavaScript treats properties within functions. The function was storing the new value and old value of the first property and not any values of the second property. The solution involved making 2 functions to test the strings in each property. Thanks for all assistance
Background
We have much of our data formatted like
var X = {value:'some val',error:'maybe an error',valid:true}
as a result we find ourselves calling X.value ALL the time.
We don't use the .error or .valid nearly as much, but we do use it.
What I want
To quit calling .value everywhere, but to still have access to meta data on a per data point level.
The Question
Is there one of
A) A way to put meta data on a primitive? attaching .error to an int for example? Is it possible for bools or strings?
B) A way to make a class that can be treated as a primitive, providing a specific data member when I do? IE X.value = 5, X+3 returns 8.
C) A better design for our data? Did we just lay this out wrong somehow?
You can set the method toString() to your object and return value.
var X = {
value: 1,
error:'maybe an error',
valid:true,
toString: function() {
return this.value;
}
}
X.value = 5;
console.log(X+3);
You can represent you data as a function object that also has properties:
var X = () => 1;
X.value = 1;
X.error = 'maybe an error';
X.valid = true,
console.log(X()); // 1
console.log(X.valid); // true
For better design you can encapsulate the creation of the data object in another function.