How to remove elements from array satisfying condition - javascript

I want to delete json elements which are satisfying the condition. For that I used the given code
var index = -1;
for (var i = 0; i < data.dashLayout.dashlets.length; i++) {
if (data.dashLayout.dashlets[i].rowNo == selectedrowno) {
if (index == -1 || data.dashLayout.dashlets[i].rowNo < data.dashLayout.dashlets[index].rowNo) {
index = i;
}
}
if (index != -1) {
data.dashLayout.dashlets.splice(index, 1);
}
}
But iteration is not completing because the data.dashLayout.dashlets.length is reducing with splice. How can I solve this issue? I want to delete all items that are satisfying the condition. Please help

Another two solutions
var a = [2,5,8,13,9,1,4,8,10], l = a.length, c = 5;
// using reverse loop
while(l--){
if(a[l] < c) a.splice(l, 1);
}
// using filter
var b = a.filter(function(e, c) {
return --e > c;
});
console.log(a); // [5, 8, 13, 9, 8, 10]
console.log(b); // [5, 8, 13, 9, 8, 10]

If you split the array in the loop .the array will be reducing you should not iterate fully , so you have to think different idea . so my solution is you have to store the index based on that you have to remove the array .In the mean time every time the index will be changed so you have to use -1
var index = -1;
var arr = [] // make array
for (var i = 0; i < data.dashLayout.dashlets.length; i++) {
if (data.dashLayout.dashlets[i].rowNo == selectedrowno) {
if (index == -1 || data.dashLayout.dashlets[i].rowNo < data.dashLayout.dashlets[index].rowNo) {
index = i;
}
}
if (index != -1) {
// data.dashLayout.dashlets.splice(index, 1);
arr.push(index); //stored it
}
}
// to remove
for(var i in arr){
if (i == 0) {
data.dashLayout.dashlets.splice(arr[i], 1); // to remove init
} else {
data.dashLayout.dashlets.splice(arr[i] - 1, 1); // now index is changed now use -1
}
}

I would recommend using the filter method of the Array object. Filter method will return a new array which only contains the elements you want. Please see the definition of the filter method here
The usage will be like the code below
var newDashlets = data.dashLayout.dashlets.filter(function(dashlet, i) {
// Here your code returns true if you want to keep dashlet.
// Return false if you don't want it.
});

in jquery
data.dashLayout.dashlets = $.grep(data.dashLayout.dashlets, function (dashList, indexpos) {
if (dashList.rowNo == selectedrowno) {
if (dashList.rowNo < data.dashLayout.dashlets[index].rowNo || index == -1) {
index = indexpos;
return false;
}
}
});

Using map in jquery
data.dashLayout.dashlets = $.map(data.dashLayout.dashlets, function (dashList, indexpos) {
if (dashList.rowNo == selectedrowno) {
if (dashList.rowNo < data.dashLayout.dashlets[index].rowNo || index == -1) {
index = indexpos;
} else {
return dashList;
}
}
});

Related

How can I check if an array includes another array? [duplicate]

I needed 2d arrays, so I made a nested array since JavaScript doesn't allow them.
They look like this:
var myArray = [
[1, 0],
[1, 1],
[1, 3],
[2, 4]
]
How can I check if this array includes a specific element (i.e. one of these [0,1] arrays) in vanilla JS?
Here is what I tried, with no success (everything returns false) (EDIT: I included the answers in the snippet):
var myArray = [
[1, 0],
[1, 1],
[1, 3],
[2, 4]
]
var itemTrue = [2, 4];
var itemFalse = [4, 4];
function contains(a, obj) {
var i = a.length;
while (i--) {
if (a[i] === obj) {
return true;
}
}
return false;
}
// EDIT: first answer's solution
function isArrayInArray(x, check) {
for (var i = 0, len = x.length; i < len; i++) {
if (x[i][0] === check[0] && x[i][1] === check[1]) {
return true;
}
}
return false;
}
// EDIT: accepted answer's solution
function isArrayInArray2(x, check) {
var result = x.find(function(ele) {
return (JSON.stringify(ele) === JSON.stringify(check));
})
return result !=null
}
console.log("true :" + myArray.includes(itemTrue));
console.log("false :" + myArray.includes(itemFalse));
console.log("true :" + (myArray.indexOf(itemTrue) != -1));
console.log("false :" + (myArray.indexOf(itemFalse) != -1));
console.log("true :" + contains(myArray, itemTrue));
console.log("false :" + contains(myArray, itemFalse));
// EDIT: first answer's solution
console.log("true :" + isArrayInArray(myArray, itemTrue));
console.log("false :" + isArrayInArray(myArray, itemFalse));
// EDIT: accepted answer's solution
console.log("true :" + isArrayInArray2(myArray, itemTrue));
console.log("false :" + isArrayInArray2(myArray, itemFalse));
It could look like duplicate but I couldn't find a similar question. If it is, feel free to tag it as such.
Short and easy, stringify the array and compare as strings
function isArrayInArray(arr, item){
var item_as_string = JSON.stringify(item);
var contains = arr.some(function(ele){
return JSON.stringify(ele) === item_as_string;
});
return contains;
}
var myArray = [
[1, 0],
[1, 1],
[1, 3],
[2, 4]
]
var item = [1, 0]
console.log(isArrayInArray(myArray, item)); // Print true if found
check some documentation here
A nested array is essentially a 2D array, var x = [[1,2],[3,4]] would be a 2D array since I reference it with 2 index's, eg x[0][1] would be 2.
Onto your question you could use a plain loop to tell if they're included since this isn't supported for complex arrays:
var x = [[1,2],[3,4]];
var check = [1,2];
function isArrayInArray(source, search) {
for (var i = 0, len = source.length; i < len; i++) {
if (source[i][0] === search[0] && source[i][1] === search[1]) {
return true;
}
}
return false;
}
console.log(isArrayInArray(x, check)); // prints true
Update that accounts for any length array
function isArrayInArray(source, search) {
var searchLen = search.length;
for (var i = 0, len = source.length; i < len; i++) {
// skip not same length
if (source[i].length != searchLen) continue;
// compare each element
for (var j = 0; j < searchLen; j++) {
// if a pair doesn't match skip forwards
if (source[i][j] !== search[j]) {
break;
}
return true;
}
}
return false;
}
console.log(isArrayInArray([[1,2,3],[3,4,5]], [1,2,3])); // true
You can't do like that .instance you have to do some thing by your own ..
first you have to do a foreach from your array that you want to search and run 'compareArray' function for each item of your array .
function compareArray( arrA, arrB ){
//check if lengths are different
if(arrA.length !== arrB.length) return false;
for(var i=0;i<arrA.length;i++){
if(arrA[i]!==arrB[i]) return false;
}
return true;
}
Here is an ES6 solution:
myArray.some(
r => r.length == itemTrue.length &&
r.every((value, index) => itemTrue[index] == value)
);
Check the JSFiddle.
Take a look at arrow functions and the methods some and every of the Array object.
The code provided by D. Young's comment that checks for any length array is faulty. It only checks if the first element is the same.
A corrected version of D. Young's comment:
function isArrayInArray(source, search) {
var searchLen = search.length;
for (var i = 0, len = source.length; i < len; i++) {
// skip not same length
if (source[i].length != searchLen) continue;
// compare each element
for (var j = 0; j < searchLen; j++) {
// if a pair doesn't match skip forwards
if (source[i][j] !== search[j]) {
break;
} else if (j == searchLen - 1) {return true}
}
}
return false;
}
For those who are interested in finding an array inside another and get back an index number, here's a modified version of mohamed-ibrahim's answer:
function findArrayInArray(innerArray, outerArray) {
const innerArrayString = JSON.stringify(innerArray);
let index = 0;
const inArray = outerArray.some(function (element) {
index ++;
return JSON.stringify(element) === innerArrayString;
});
if (inArray) {
return index - 1;
} else {
return -1;
}
}
findArrayInArray([1, 2, 3], [[3, .3], [1, 2, 3], [2]]); // 1
findArrayInArray([1, 2, 3], [[[1], 2, 3], [2]]) // -1
This function returns the index of the array you are searching inside the outer array and -1 if not found.
Checkout this CodePen.

splice function does not work properly in 1 items array

In my Laravel 5/vuejs 2/ vuex app I make deletion of an row in db and use splice function to remove item from the array as:
axios({
method: ( 'delete' ),
url: this.getters.apiUrl + '/personal/hostel_bookmarks/' + this.getters.currentLoggedUser.id + "/" + relatedHostel.id,
}).then((response) => {
let L = this.getters.hostelBookmarks.length
for (var I = 0; I < L; I++) {
if (relatedHostel.id == this.getters.hostelBookmarks[I].hostel_id) {
// this.getters.hostelBookmarks.splice(this.getters.hostelBookmarks.indexOf(this.getters.hostelBookmarks[I]), 1)
this.getters.hostelBookmarks.splice(I, 1)
context.commit('refreshHostelBookmarks', this.getters.hostelBookmarks);
break;
}
}
bus.$emit( 'onHostelBookmarkDeleteSuccess', response );
}).catch((error) => {
bus.$emit('onHostelBookmarkDeleteFailure', error);
});
It works ok if this.getters.hostelBookmarks has more 1 elements, but if it has only 1 items then it is not deleted, but how error in js console...
How to fix ?
This should fix your problem
let index = this.getters.hostelBookmarks.findIndex(item => { return item.hostel_id === relatedHostel.id })
if (index !== -1) {
this.getters.hostelBookmarks.splice(index, 1)
context.commit('refreshHostelBookmarks', this.getters.hostelBookmarks);
}
Can you try the following code?
let L = this.getters.hostelBookmarks.length;
for (var I = L-1; I >= 0; I--) {
if (relatedHostel.id == this.getters.hostelBookmarks[I].hostel_id) {
this.getters.hostelBookmarks.splice(I, 1);
context.commit('refreshHostelBookmarks', this.getters.hostelBookmarks);
break;
}
}
demo code for ++, --:
If you have an array [1, 2, 3, 4, 5]. And you want to remove the 2nd and 4th element, 2 and 4.
First ++:
const origin = [1,2,3,4,5];
for(var i = 0; i < origin.length; i++){
if(i === 1 || i === 3) {
origin.splice(i, 1);
}
}
console.log(origin); // [1, 3, 4]
As you can see, the result is not you expected. If you log the every element in loop, you will see the index of element was changed after the element 2 was deleted. When i is 3 in the loop, actually, the 5th element will be deleted.
Then let's have a look in --:
const origin = [1,2,3,4,5];
for(var i = origin.length; i >= 0; i--){
if(i === 3 || i === 1) {
origin.splice(i, 1);
}
}
console.log(origin); // [1, 3, 5]
This is what you want. When --, we will remove the element from the last to the first. The index of element is not changed.

Javascript: Write a function that takes in an array, and then returns an array with only unique numbers, only arrays removed

Write a function that takes in a list and returns a list with all of the duplicates removed (list will only have unique numbers).
Here's what I have so far:
var lista = [1,4,5,1,1,3,5,6,4,4,3];
function dupRemove (lista) {
//Sort the array in case it isn't sorted
lista.sort();
//Object to store duplicates and unique numbers
var listNumbers = {
"Duplicate Numbers": [],
"Unique Numbers": []
};
for (var i = 0; i < lista.length; i++) {
//check if it is not equal to the index of the array before it and after. if it isn't, that means its unique, push it in the uniques array.
if (lista[i] !== lista[i-1] && lista[i] !== lista[i+1]) {
listNumbers["Unique Numbers"].push(lista[i]);
} else {
listNumbers["Duplicate Numbers"].push(lista[i]);
}
}
return listNumbers;
}
Currently, my solution returns an object with keys with the values of "Duplicates": 1, 1, 1, 3, 3, 4, 4, 4, 5, 5 and "Uniques": 6.
How do I remove the duplicates from duplicates and then join these two keys into a single array?
Thank you.
that answer is seriously over -engineered- all you need to to is push all values into a new array if they are not already in it.
function=removeDups()
{
var lista = [1,4,5,1,1,3,5,6,4,4,3];
var uniqueValues=[];
var duplicateValues=[];
for(i=0;i<lista.length;i++)
{
if(uniqueValues.indexof(lista[i] == -1){uniqueValues.push(lista[i]}else{duplicateValues.push(lista[i]}
}
}
You could just use the default filter method that is on all Arrays
You don't need the sort function either. If the item is already found using the indexOf method it will not be added to the newly returned array created by the filter method
var list = [1,4,5,1,1,3,5,6,4,4,3];
function removeDup (arr) {
return arr.filter(function(item, pos) {
return arr.indexOf(item) == pos;
})
}
var sortedList = removeDup(list).sort(function(a,b){
return a - b
})
document.getElementsByTagName('div')[0].textContent = sortedList
<div></div>
Kind of a non elegant solution but it gives you the two arrays: one with the duplicate values and one with the unique ones. Since you cannot rely on .sort() you can just count things.
Function checkList will give you back those two arrays.
var list = [1,4,5,1,1,3,5,6,4,4,3];
console.log(checkList(list));
function checkList(list) {
var uniques = []; // will be [6]
var dups = []; // will be [1, 4, 5, 3]
var checked = []; // save what you have already checked so far
for(i = 0; i < list.length; i++) {
if(notChecked(list[i], checked)) {
checked.push(list[i]);
if(count(list[i], list) > 1) {
dups.push(list[i]);
} else {
uniques.push(list[i]);
}
}
}
return {dups: dups, uniques: uniques}
}
// count how many num in arr
function count(num, arr) {
var count = 0;
var i;
for(i = 0; i < arr.length; i++) {
if(arr[i] == num) count++;
if(count > 1) return count;
}
return count;
}
// check if num has not been checked
function notChecked(num, arr) {
return (arr.indexOf(num) == -1) ? true : false;
}

angularjs remove array specific element dosen't work

if I push two elements into another array and then try to remove the first one ( click at the first button ) the second element is being removed. why ?!?
DEMO
$scope.removeFromList = function(p) {
$scope.found = $.grep($scope.data2, function(e) {
return e.ID == p.ID;
});
var index = $scope.data2.indexOf($scope.found);
$scope.data2.splice(index, 1);
}
indexOf works for array not for Object. It returns -1, and so always take the last element.
Try this:
$scope.removeFromList = function (p) {
var index = $scope.data2.map(function(e) { return e.ID;}).indexOf(p.ID);
if(index >= 0)
$scope.data2.splice(index, 1);
}
This is happend because indexof is not used to find the objects and return -1 index always which in turn remove the first element always you need to create your own indexof
var index = myIndexOf($scope.data2,$scope.found);
function myIndexOf(arr,o) {
for (var i = 0; i < arr.length; i++) {
if (arr[i].x == o.x && arr[i].y == o.y) {
return i;
}
}
return -1;
}
Plunker

Remove array of indexes from array

John Resig, creator of jQuery created a very handy Array.remove method that I always use it in my projects:
// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
// Remove the second item from the array
array.remove(1);
// Remove the second-to-last item from the array
array.remove(-2);
// Remove the second and third items from the array
array.remove(1,2);
// Remove the last and second-to-last items from the array
array.remove(-2,-1);
It works great. But I would like to know if it's extendable so that it can take an array of indexes as the first argument?
Otherwise, I will probably make another method that makes use of it:
if (!Array.prototype.removeIndexes) {
Array.prototype.removeIndexes = function (indexes) {
var arr = this;
if (!jQuery)
throw new ReferenceError('jQuery not loaded');
$.each(indexes, function (k, v) {
var index = $.inArray(v, indexes);
if (index !== -1)
arr.remove(index);
});
};
}
If Array.remove() isn't extendable to fit my needs, what do you think about my other solution above?
I think this is what you are looking for (It works with negative index too) :
if (!Array.prototype.removeIndexes) {
Array.prototype.removeIndexes = function (indexes) {
var arr = this;
if (!jQuery) throw new ReferenceError('jQuery not loaded');
var offset = 0;
for (var i = 0; i < indexes.length - 1; i++) {
if (indexes[i] < 0)
indexes[i] = arr.length + indexes[i];
if (indexes[i] < 0 || indexes[i] >= arr.length)
throw new Error('Index out of range');
}
indexes = indexes.sort();
for (var i = 0; i < indexes.length - 1; i++) {
if (indexes[i + 1] == indexes[i])
throw new Error('Duplicated indexes');
}
$.each(indexes, function (k, index) {
arr.splice(index - offset, 1);
offset++;
});
return arr;
};
}
var a = ['a', 'b', 'c', 'd', 'e', 'f'];
var ind = [3, 2, 4];
a.removeIndexes(ind);
console.log(a.join(', '));
// returns : a, b, f
See fiddle
This version should work. It modifies the original array. If you prefer to return a new array without modifying the original, use the commented out initializer of result and add return result at the end of the function.
Array.prototype.removeIndexes = function(indices) {
// make sure to remove the largest index first
indices = indices.sort(function(l, r) { return r - l; });
// copy the original so it is not changed
// var result = Array.prototype.slice.call(this);
// modify the original array
var result = this;
$.each(indices, function(k, ix) {
result.splice(ix, 1);
});
}
> [0, 1, 2, 3, 4, 5, 6, 7, 8].removeIndexes([4, 5, 1]);
> [0, 2, 3, 6, 7, 8]
How about
Array.prototype.remove = function (indexes) {
if(indexes.prototype.constructor.name == "Array") {
// your code to support indexes
} else {
// the regular code to remove single or multiple indexes
}
};

Categories

Resources