Javascript Filter Refactor - javascript

I am filtering an array of objects using a function that looks like this
var val = 'some text value'
this.someList = this.someList.filter(containsQuery);
function containsQuery(listItem) {
return listItem.Key_One.toLowerCase().indexOf(val) > -1 ||
listItem.Key_Two.toLowerCase().indexOf(val) > -1 ||
listItem.Key_Three.toLowerCase().indexOf(val) > -1
}
My question is what is a better way of filtering on each of the list item key values without having to write a new line for each one? i.e so I can avoid going
listItem.Key_Four.toLowerCase().indexOf(val) > -1
listItem.Key_Five.toLowerCase().indexOf(val) > -1
etc..
Any advice would be great.
Thanks!

You could use get keys of the object with Object.keys and iterate with Array#some.
function containsQuery(listItem) {
return Object.keys(listItem).some(function (k) {
return listItem[k].toLowerCase().indexOf(val) > -1;
});
}

Just a suggestion, array containing all the keys and loop them?
Like
var keys = ['key_one', 'key_two', 'key_three', 'key_four'];
for (i=0; i<keys.length; i++){
if (listItem[keys[i]].toLowerCase().indexOf(val) > -1) return true;
}
return false;
Ah damn, same idea as above, just took too long writing :D

Related

Split and find the value exists using JavaScript

I have an array like
[test1^^^68936^^^2017-06-05^^^274^^^NO^^^location1^^^1840, test2^^^68766^^^2016-06-05^^^274^^^NO^^^location2^^^1840,test3^^^68966^^^2017-06-05^^^274^^^YES^^^location1^^^1840]
where I need to split it and find out whether the fourth key in that array of keys has NO or YES or 1. If both NO and YES exists in an array, I need to alert the user that they have both of them in it.
please let me know how to do it in JavaScript.
You can achieve this without split() also:
var array = ['test1^^^68936^^^2017-06-05^^^274^^^NO^^^location1^^^1840', 'test2^^^68766^^^2016-06-05^^^274^^^NO^^^location2^^^1840','test3^^^68966^^^2017-06-05^^^274^^^YES^^^location1^^^1840'];
var arrayStr = array.toString();
if(arrayStr.indexOf('^^^YES') !== -1 && arrayStr.indexOf('^^^NO') !== -1){
alert('You have both of them in it');
}else{
alert('You do not have both of them in it');
}
Assuming that your array contains strings
["test1^^^68936^^^2017-06-05^^^274^^^NO^^^location1^^^1840", "test2^^^68766^^^2016-06-05^^^274^^^NO^^^location2^^^1840","test3^^^68966^^^2017-06-05^^^274^^^YES^^^location1^^^1840"]
You can get the YES/NO keys by mapping the array and splitting it like this
["test1^^^68936^^^2017-06-05^^^274^^^NO^^^location1^^^1840", "test2^^^68766^^^2016-06-05^^^274^^^NO^^^location2^^^1840","test3^^^68966^^^2017-06-05^^^274^^^YES^^^location1^^^1840"].map(function(str){return str.split("^^^")[4]})
Try this
res = arr.join("").match(/NO|YES/g)
if(res.includes("YES") && res.includes("NO")){
console.log("Both present")
}
I tried and got solved
var arrayStr = myarray.toString();
var stringExists = [];
if(arrayStr.indexOf('^^^NO^^^') !== -1) {
stringExists.push('0');
}
if(arrayStr.indexOf('^^^YES^^^') !== -1) {
stringExists.push('1');
}
if (stringExists.length > 1) {
alert("Error");
return;
}
Thanks for all your support guys..

Get index of item in array found with filter Angular Javascript

I have an array of pages in a book. I would like to find the index of a page that I have used filter to find. I'm farming it out to a function which works, but I wonder I can't combine indexOf or findIndex or something similar with the filter?
To get a specific page, I use this code:
getPage(pageNumber: number) {
return this.pages.filter(page => page.pageNumber == pageNumber)[0];
}
Then, to delete a page I use the following:
deletePage() {
let deletedPageLocation = this.findPageIndex();
this.pages.splice(deletedPageLocation, 1);
this.pagesChanged.next(this.pages.slice());
}
findPageIndex() {
for(var i=0; i < this.pages.length; i++) {
if (this.pages[i].pageNumber == this.currentPage) {
return i;
}
}
I would like to simplify into something like:
let deletedPageLocation = this.pages.indexOf(this.pages.filter(page => page.pageNumber == pageNumber)[0]);
But I couldn't figure out a way to get it to return the value. Any suggestions?
var found = $filter('filter')($scope.pages, { pageNumberinPages: pagenumberSearching },true);
It will return you array of objects matches your search.
I hope this helps.
You can also do it by using find and indexOf. I find it much easier than using filter. Here's a code sample in terms of your question:
deletePage(item){
let deleteItem = this.pages.find(this.findIndexToUpdate, item.pageId);
let index = this.pages.indexOf(deleteItem);
if(index > -1){
this.pages.splice(index, 1);
}
}
findIndexToUpdate(item) {
console.log("this: " + this)
return item.pageId === this;
}
Plunker demo

How to insert a string in an array with a specific order

So I have the following array :
let array = ['9h00','9h30','9h45','10h00','10h15']
Let's say I want to insert '9h15' between '9h00' && '9h30'
How would one do it in a fast & efficient solution ?
EDIT: I have been unclear, the index of the insert would change depending on the array. It won't always be the following position : array[1].
Thanks in advance!
If every item has the same format (\d?\d)h(\d{2}) then we can do the following :
First we need a function to convert the string to an object or something we can work with, I'll go with an object :
function timeStringToObj(str){
var re = "^(\d?\d)h(\d\d)$";
var h = str.replace(re, "$1");
var m = str.replace(re, "$2");
return {
hours: parseInt(h),
minutes: parseInt(m)
};
}
Then we will need to ensure that the array is sorted, for instance "9h15" < "9h16" therefore "9h15"'s index is < "9h16"'s index , (if not use array.sort(/*some sorting function if necessary*/)) and loop through it to find the spot (I'll use a function of course), I'll consider your array as a global variable :
/**
*#param timeObjA an object that is the return value of a call of timeStringToObj
*#param timeObjB an object that is the return value of a call of timeStringToObj
*/
function AgeB(timeObjA, timeObjB){//A greater than or equal to B
return (timeObjA.hours >= timeObjB.hours && timeObjA.minutes >= timeObjB.minutes);
}
/**
*#param a an object that is the return value of a call of timeStringToObj
*#param b an object that is the return value of a call of timeStringToObj
*/
function AleB(a, b){//A less than or equal to B
return (timeObjA.hours <= timeObjB.hours && timeObjA.minutes <= timeObjB.minutes);
}
function putInTimeArray(str){
var val = timeStringToObj(str);
for(let i = 0 ; i < array.length ; i+=1){
var curr = timeStringToObj(array[i]);
//first check : elem >= last
if( AgeB(val, curr) && i===(array.length-1) ){
array.push(str);
return true;
}
//second check : elem <= first
if( AleB(val, curr) && i===0 ){
array.unshift(str);
return true;
}
//last check : first < elem < last
if(i!=0 && i!=(array.length - 1)){
if(AgeB(val, curr)){
array.splice(i+1,0,str);
return true;
}
if(AleB(val, curr){
array.splice(i-1,0,str);//here i-1 is safe since i!=0 (condition)
return true;
}
}//end of last check
}//end of for-loop
}//end of function
If you're having doubts regarding my usage of splice please refer to this : How to insert an item into an array at a specific index?
EDIT
You'll probably need a more sophisticated regex to be more appropriate be this will do the job just fine if you don't go that crazy with those strings
You can push and sort like:
array.push("9h15").sort().reverse(); // ["9h45", "9h30", "9h15", "9h00", "10h15", "10h00"]

Checking a 2D Array Bounds in Javascript

I have a 2-dimensional array that I want to check the bounds in Javascript. I prefer doing this without checking each index independently.
For example if my 2d array is...
dataset[row0-1][column+column0]
I really do not want to have to do the following...
if(row0-1 >0)
{
if(dataset[row0-1].length >= column+column0)
{
data = {label : dataset[row0-1][column+column0]};
}
}
The problem is that I have to first check the row and then check the column. I prefer doing both of these checks with one operation or on one line. Rather then returning an out of bounds error, why doesn't Javascript just return null or undefined?
For example, in a future version of Javascript, wouldn't it be better if we could do this?
if(dataset[row0-1][column+column0] != undefined)
{
data = {label : dataset[row0-1][column+column0]};
}
else
{
...
}
You can write a function to check:
function CheckArrayIndex(x, y) {
if (dataset.length > x && dataset[x].length > y) {
return dataset[x][y];
}
return null;
}
Then you can use it like this:
if(CheckArrayIndex(row0-1,column+column0) != null){
data = {label : dataset[row0-1][column+column0]};
}
I think the reason for checking each index independently is because each dimension can have different lengths on each index.
I know C# has Multidimensional Arrays, but Javascript uses Jagged Arrays.
I do not picture this changing any time soon.
You can easily combine nested if-clauses to a one-liner using the AND-operator &&:
if (row0-1 > 0 && dataset[row0-1].length >= column+column0){
data = {label : dataset[row0-1][column+column0]};
}
although you really should check for the array's length, not (only) greater-than 0. Better:
if (row0-1 > 0 && row0-1 < dataset.length && column+column0 < dataset[row0-1].length)
data = {label: dataset[row0-1][column+column0]};
}
I do mostly like this: say we have 2d array arr and we need to access an element which isn't there.
var arr = [/*elements*/]
var get = function(x, y) {
if(!arr[x]) {
return false;
}
return arr[x][y] || false;
}
Using the #dmck answers, I use prototype in Array object.
Function:
Array.prototype.CheckBounds = function (x, y)
{
if (this[x] === undefined)
return false;
if (this.length > x && this[x].length > y) {
return true;
}
return false;
}
How to use:
if(myArray.CheckBounds(5,10)) //Check bounds
{
//OK
}else{
//Out of bounds
}

Call a function if a string contains any items in an array

How can I call a JavaScript function if a string contains any of the items in an array?
Yes, I can use jQuery :)
You could use the grep function to find if there are any elements that satisfy the condition:
// get all elements that satisfy the condition
var elements = $.grep(someArray, function(el, index) {
// This assumes that you have an array of strings
// Test if someString contains the current element of the array
return someString.indexOf(el) > -1;
});
if (elements.length > 0) {
callSomeFunction();
}
You could use some(), a Mozilla extension which has been added to ECMAScript 5:
var haystack = 'I like eggs!';
if(['spam', 'eggs'].some(function(needle) {
return haystack.indexOf(needle) >= 0;
})) alert('spam or eggs');
Simply loop over the items in the array and look for the value. That's what you have to do anyway even if you use some method to do it for you. By looping yourself you can easily break out of the loop as soon as you find a match, that will by average cut the number of items you need to check in half.
for (var i=0; i<theArray.length; i++) {
if (theArray[i] == theString) {
theFunction();
break;
}
}

Categories