Matching all values, substitute to OR operator - javascript

Here is a first sample of code that work as intended: on the rest of the code this is used as a filter and will match 2 items from myids, those 2 where objectId match tWOsQhsP2Z and sStYrIU6lJ:
return myids.objectId === "tWOsQhsP2Z" || myids.objectId === "sStYrIU6lJ";
Because I need to pass arbitrary number of ids from an array, i'm trying to refactor code like so:
return myids.objectId === ("tWOsQhsP2Z" || "sStYrIU6lJ");
Problem with this new code is that filter that use return value will return only one item, the one with objectId that is tWOsQhsP2Z.
Do you know a way how I could refactor this second code so I keep single code "myids.objectId" but return match for ALL objectIds values ?

Sounds like you need something like underscore.js contains() method, would make things a lot simpler all round.
e.g.
return _.contains(arrayOfIds, myids.objectId);

You can use a switch:
switch (myids.objectId) {
case "tWOsQhsP2Z":
case "sStYrIU6lJ":
return true;
}
return false;

If you have an array of values to search, and the list is long and/or you're searching frequently, you can convert the list to an object and then do a property lookup. It's much more efficient that searching through an array.
For a simple constant case, your example would look like:
return myids.objectId in {"tWOsQhsP2Z": 1, "sStYrIU6lJ": 1};
If you start with an array that's server-generated or dynamic:
var knownIds = [ ... ];
then you can convert that to a map:
var idMap = knownIds.reduce(function(m, v) {
m[v] = 1;
return m;
}, {});
Now your lookup would be simply:
return myids.objectId in idMap;

Related

How to calculate the number of objects I get from the loop Javascript

I filtered my set of users(array) with if(elem.id_verified). I now get 77 users objecta. I just want to take the number of these objects. I tried with console.log(this.numOfunverifiedUsers.length) but i get 77 underfined. My question is how to assemble all objects and get that number. Maybe my logic is going in the wrong direction.
this.users=response.data.users
this.numOfunverifiedUsers = []
this.users.forEach(elem => {
if (elem.id_verified === 0) {
this.numOfunverifiedUsers = elem
console.log(this.numOfunverifiedUsers.length)
}
})
this.numOfunverifiedUsers.push(elem)
Push the element in array.
this.numOfunverifiedUsers = elem , replace it with above
This should work too:
console.log(this.users.filter(function (val) {
return val.id_verified === 0
}).length)
filter items that are id_verified === 0 and count their length.
I think would be better you build that list with a filter:
this.numOfunverifiedUsers = this.users.filter(
user => user.id_verified === 0
);
console.log(this.numOfunverifiedUsers);
console.log(this.numOfunverifiedUsers.length);
If you want to read about filter: Filter method
With this.numOfunverifiedUsers = elem, you are assigning 'elem' to an array reference. As a result, you get exceptions which make the '=' operator return the undefined primitive type (as the result of function errors; see undefined - JavaScript | MDN). What you want to do is either add the element iteratively into the array the "old way", via element assigning, or just use the OOP way via the push method. The former wouldn't require a count function, as you can do something like that:
var count = 0; //outside the forEach
...
if (elem.id_verified === 0) {
{
this.numOfunverifiedUsers[count++]=elem
console.log(count)
}
...
However, as others pointed out, using a filter makes the code much more clean and readable
This would work better with the use of a Filter
console.log(this.users.filter(function (val) {
return val.id_verified === 0
}).length)
filter items that are id_verified === 0 and count their length.

Javascript return statement inside filter function, get uniques. Why code works?

I have a big array of objects where I need to get the unique values for some keys.
I have the code working, but I would like to understand it.
Object
{
"cor": {
"id": 89,
"code": "192"
},
"tamanho": {
"id": 74,
"code": "L"
},
"price": "56,34",
"prevPrice": "93,90",
"stock": 0
}
And this is the iteration that return only unique values.
What I can't understand is the return statement, how does javasacript reads it?
var tamanhos = [];
data.grelha.filter(function(el, i, arr) {
return tamanhos.indexOf(el.tamanho.id) == -1 && tamanhos.push(el.tamanho.id);
});
Thanks a lot!
Before I get to what I think you're asking, let's talk about .filter(). Firstly, it returns a new array, so calling .filter() without using its return value is not how you are supposed to use it: if you just want to iterate over the array you should use .forEach() instead. It works by calling the function you pass it once per array element. Only elements for which your function returns a truthy value will be added to the output array. The correct way to use .filter() to solve this problem would be something like this:
var tamanhos = data.grelha.map(el) { return el.tamaho.id }).filter(function(el, i, arr) {
return arr.indexOf(el) === i
})
That is, first use .map() to get a list of all the IDs, then use .filter() to only keep elements if they are the first occurrence of that ID in the array, thus setting tamanhos to be an array of unique IDs.
Now to what you seem to be asking, which is for an explanation of what the following line is doing:
return tamanhos.indexOf(el.tamanho.id) == -1 && tamanhos.push(el.tamanho.id);
The key is the && (logical AND) operator. It uses short circuit evaluation, which means that the expression on the right-hand-side of the && will only be evaluated if the expression on the left-hand-side is truthy.
Two simple examples (click "Run"):
true && alert('This WILL display because alert() is called.');
false && alert('This will NOT display because alert() is not called');
So if tamanhos.indexOf(el.tamanho.id) == -1 is true then the tamanhos.push(el.tamanho.id) part will be executed, otherwise the .push() will not be executed. In other words, the part after the return is equivalent to doing this:
if (tamanhos.indexOf(el.tamanho.id) == -1) {
tamanhos.push(el.tamanho.id);
}
(That is, if the item isn't already in the tamanhos array then add it.)
The result of the whole && expression is then returned, but as mentioned above that is not really relevant because you don't use the return value from .filter(). So what your code is doing is equivalent to this:
var tamanhos = [];
data.grelha.forEach(function(el) {
if (tamanhos.indexOf(el.tamanho.id) == -1) {
tamanhos.push(el.tamanho.id);
}
});
this is a json datas. Json values can use array. I think, you know arrays. So Arrays has multi areas. Like :
[val1]
[val1, val2]
[val1, val2, val3]
[val1, val2, val3, .....]
we can take values as column name. Example for c#:
array[] names = new array["mesut", "joa"]
you have javascript arrays

Check if the first letter of each element of an array is capital using filter method. But I keep getting the whole array

// JavaScript Document
"use strict";
var testArray =["beau","Diane","morgan","Brittany"];
function checkCapital(value,index,array) {
if(value!==value.charAt(0).toLowerCase())
return value;
}
var capital =testArray.filter(checkCapital);
console.log(capital);
I need to check if the first letter of every value of the array is a capital using filter method. But I keep getting the whole array returned on my function.
Well, you are comparing an entire string with the lowercase equivalent of its first character, which is a problem. And you are going to return undefined when your condition is not satisfied, and a specific character if it is, which is a little strange. Your filter function should be
return value.charAt(0) !== value.charAt(0).toLowerCase()
or use the more modern
return value[0] !== value[0].toLowerCase()
and write the whole app in more modern JavaScript as follows:
const testArray = ["beau", "Diane", "morgan", "Brittany", "^&#SYMBOLS$$--"];
const capital = testArray.filter(s => s[0] !== s[0].toLowerCase());
console.log(capital);
but really, what is and is not an uppercase letter is an interesting problem in its own right. What if a word starts with a comma? A Cherokee or Devanagari letter? Letter-like symbols? If you really want to do uppercase properly, you might want to get a package like xregexp then you can write a filter function that matches XRegExp("^\\p{Lu}"). I understand this might be beyond what you are looking for at the moment, but it's a good thing to know about.
The filter() method depends on the return statement of the callback, which if returns true then filter() will include the current value to the array it will return. Just remove your if statement and put the condition on the return statement:
function checkCapital(value,index,array) {
return value !== value.charAt(0).toLowerCase();
}
Because your original callback returns true always, it would include all elements of the original array to be returned by the filter() method.
First off you are always returning value from your filter function, that is the core reason why you are getting the whole array. A filter function shold return true or false depending on whether the value should or should not be included in the output.
You have other issues with your code but try and solve them on your own.
solution :-
function checkUppercase(arr)
{
var array1 = arr.split(' ');
var newarray1 = [];
for(var x = 0; x < array1.length; x++){
newarray1.push(array1[x].charAt(0).toUpperCase()+array1[x].slice(1));
}
newarray1.join(' ');
let i=0;
if(JSON.stringify(array1) == JSON.stringify(newarray1)) {
return true
}else {
return false;
}
}
console.log(checkUppercase("solid Is Transparent"));

Javascript String replacer for custom template

I would like to get some ideas how to achieve the following task.
I'm writing a lightweight template language. That takes any array or json object and replaces the string-values with values from my local data store.
Please let me illustrate how it works:
var obj = {
prop: "_p{propnameA}",
secondprop: "_p{propnameB}",
thirdprop: "Hello, this is \"_p{propnameC}\" and _p{propnameD},
arr: [
"textvalue", "propB value = _p{propB}"
]
}
I've wrote an algorithm that iterates over each property of each json or array. Now i need a fast way to replace all my template-tags to their actual values.
I would like to use different types of template-tags:
_p{...}
_c{...}
_v{...}
etc.
each template-tag means something different in my program. For Example: the template-tag _p{} calls a method in my application with the parameter of the tag-value. _p{propval} is a equivalent to myApp.getProperty("propval")
Other tags call other methods of my application.
I am thinking about using a string.replace with a regular expression for my tags. But i run into two problems:
How to write this regular expression?
How to handle non-string return values?
the evaluated value of a tag must not always be a string. it could also be a more complex data type like an array or json object. In my first example code at the top of this question the resulting value for "_p{propnameA}" could be an array like [1,2,3,4]. Or _p{propnameB} could be a number and so my example on top should evaluate like:
obj = {
prop: [1, 2, 3, 4],
secondprop: 827,
thirdprop: "Hello, this is \"valueC\" and valueD",
arr: ["textvalue", "propE value = 827"]
}
obviously obj.secondprop should not have the string value "827" but the number instead while obj.arr[1] should be a string.
Do you got some smart ideas how to do this?
Thank you very much for any help!
If I understood correctly, you're looking for something like this:
// evaluate a single placeholder like _p{foo}
function evalPlaceholder(prefix, content) {
switch(prefix) {
case "_p": do_this();
case "_c": do_that();
//etc
}
}
// eval a string with placeholders
function evalTemplate(str) {
var m = str.match(/^(_\w){([^{}]+)}$/);
if(m) {
// the whole string _is_ a placeholder
return evalPlaceholder(m[1], m[2]);
}
// otherwise, the string can _contain_ placeholders
return str.replace(/(_\w){(.+?)}/g, function(_, $1, $2) {
return evalPlaceholder($1, $2);
});
}
// walk an object recursively and eval all templates
function evalObject(obj) {
Object.keys(obj).forEach(function(k) {
var v = obj[k];
if(typeof v == "object")
evalObject(v)
else
obj[k] = evalTemplate(v);
})
}
first, you can cast numeric values to strings in two ways, which I am sure you have seen something like this before:
1- toString function call: var x = 825; console.log(x.toString())
2- adding the number to a string: var x = '' + 825
so if you don't want numeric values, but only strings, just make sure you convert the value to string (even if it's a string nothing will happen) before you use it.
second, I don't think I really got your problem, but from what I got, your problem is much simpler that a regex, you're only replacing well defined string, so while iterating over the values all you need is:
var p = prop.toString();
if(p.startsWith("_p") {
p.replace("_p", "_c)
}
I hope this is what you are looking for

counting object properties with underscore.js

So I'm trying to think of a better way to do this with underscore:
state.attributes = _.reduce(list, function(memo, item){
memo['neighborhood'] = (memo['neighborhood'] || []);
var isNew = true;
_.each(memo['neighborhood'], function(hood){
if (hood.name === item.data.neighborhood) {
hood.count++; isNew=false;
}
});
if(isNew){
memo['neighborhood'].push({name:item.data.neighborhood, count:1});
}
return memo;
});
I would like to combine the various names of the list into a list of unique names with a count of how many times each unique name occurs. It seems like exactly the kind of problem underscore was designed to solve, yet the best solution I could think of seems less than elegant.
I'm not an underscore.js user, but I guess _.groupBy() suits this scenario:
var attributes = _.groupBy(list, function (item) {
return item.data.neighborhood
})
It doesn't returns an array in the exact way you want, but it contains all the information you need. So you have in attributes["foo"] all the items that have "foo" as neighborhood value property, and therefore in attributes["foo"].length the count of them.
Maybe there is a better underscore.js way, but you can already apply other optimizations:
Instead of using an array to keep track of the name and the count, use a name: count map. This can be easily done with an object:
state.attributes = _.reduce(list, function(memo, item){
var n = item.data.neighborhood;
memo['neighborhood'] = (memo['neighborhood'] || {});
memo['neighborhood'][n] = memo['neighborhood'][n] + 1 || 1;
return memo;
});
This works, because if item.data.neighborhood is not in the list yet, memo['neighborhood'][item.data.neighborhood] will return undefined and undefined + 1 returns NaN.
Since NaN evaluates to false, the expression NaN || 1 will result in 1.

Categories

Resources