splice not working while using in for loop - javascript

i am trying to remove an item from array but its not working i am using following code
vm.Continue = function () {
$scope.invalidList = [];
if (vm.errorexsist === true) {
var table = document.getElementById('errortabel');
for (var r = 0, n = table.rows.length; r < n; r++) {
if (r > 0) {
$scope.invalidList.push({
Error: table.rows[r].cells[0].val ,
FirstName: table.rows[r].cells[1].children[0].value,
Email: table.rows[r].cells[2].children[0].value,
PhoneNumber: table.rows[r].cells[3].children[0].value,
Location: table.rows[r].cells[4].children[0].value,
Department: table.rows[r].cells[5].children[0].value
});
}
}
var i = $scope.invalidList.length;
while (i--) {
if (IsEmailValid($scope.invalidList[i].Email) === true && IsPhoneNumValid($scope.invalidList[i].PhoneNumber) === true) {
$scope.invalidList.splice(i, 1);
}
}
}
};
the above code always removes item at zero while condition of if else does not meet.

Array.splice will modify the length of an array, so you should iterate backwards through your array otherwise every time you call splice, the index and length of your for loop become obsolete.
var i = $scope.invalidList.length
while (i--) {
if (IsEmailValid($scope.invalidList[i].Email) === true && IsPhoneNumValid($scope.invalidList[i].PhoneNumber) === true) {
$scope.invalidList.splice(i, 1);
}
}
If you're looking to remove items from an array based on a condition, Array.filter is designed for this exact purpose:
$scope.invalidList = $scope.invalidList.filter(item => !IsEmailValid(item.Email) || !IsPhoneNumValid(item.PhoneNumber))

Related

How can i remove the duplicated elements in my array?

I used this code but with that i can only remove the next one and the previuous one if its equal
for (let i = 0; i < this.userlist.length; i++) {
if (this.userlist[i] == this.userlist[i+1])
this.userlist.splice(i+1, 1);
if (this.userlist[i-1] == this.userlist[i+1])
this.userlist.splice(i+1, 1);
}
How can i remove all the duplicated elements?
edit n°1
data() {
return {
formlogin: "",
userID: "Guest",
logged: false,
userlist: []
};
},
mounted() {
this.userID = localStorage.getItem("userID");
if (this.userID != "Guest") this.logged = localStorage.getItem("logged");
if (localStorage.userlist)
this.userlist = JSON.parse(localStorage.getItem("userlist"));
},
props: {},
methods: {
login: function() {
if (this.formlogin != "") {
this.userID = this.formlogin;
this.formlogin = "";
this.logged = true;
localStorage.setItem("logged", this.logged);
localStorage.setItem("userID", this.userID);
this.userlist.push(this.userID);
for (let i = 0; i < this.userlist.length; i++) {
if (this.userlist[i] == this.userlist[i + 1])
this.userlist.splice(i + 1, 1);
if (this.userlist[i - 1] == this.userlist[i + 1])
this.userlist.splice(i + 1, 1);
}
localStorage.setItem("userlist", JSON.stringify(this.userlist));
console.log("data sent :", this.userID, this.logged);
alert("Welcome : " + this.userID);
} else alert("cant login with a null username");
},
thats how my userlist will be updated.
es6 spread operator with Set()
var items = [4,5,4,6,3,4,5,2,23,1,4,4,4];
console.log([...new Set(items)]);
OR,
var items = [4,5,4,6,3,4,5,2,23,1,4,4,4];
console.log(Array.from(new Set(items)));
Using filter method
var items = [4,5,4,6,3,4,5,2,23,1,4,4,4];
var newItems = items.filter((item, i) => items.indexOf(item) === i);
console.log(newItems);
Using reduce method
var items = [4,5,4,6,3,4,5,2,23,1,4,4,4];
var newItems = items.reduce((uniq, item) => uniq.includes(item) ? uniq: [...uniq, item], []);
console.log(newItems);
You almost got it!
for (let i = 0; i < this.userlist.length; i++) {
if (this.userlist[i] == this.userlist[i+1]){
this.userlist.splice(i+1, 1);
i--;
}
}
In your solution, two elements are removed at most. What you can do instead is remove the next element an make sure that the index doesn't increase (hence the i--, so in the next iteration if will check the same index again).
This however only works for sorted lists. Check solanki's answer for a more generic one.
Using reduce you can do something like this. Check if the current index is same as the first index found in data
var data = ["user", "user", "user", "foo", "foo"]
var res = data.reduce((acc, elem, idx, arr)=> (arr.indexOf(elem) === idx ? [...acc, elem] : acc),[]);
console.log(res)

Count the number of unique occurrences in an array that contain a specific string with Javascript

Here is my javascript array:
arr = ['blue-dots', 'blue', 'red-dots', 'orange-dots', 'blue-dots'];
With Javascript, how can I count the total number of all unique values in the array that contain the string “dots”. So, for the above array the answer would be 3 (blue-dots, orange-dots, and red-dots).
var count = 0,
arr1 = [];
for (var i = 0; i < arr.length; i++) {
if (arr[i].indexOf('dots') !== -1) {
if (arr1.indexOf(arr[i]) === -1) {
count++;
arr1.push(arr[i]);
}
}
}
you check if a certain element contains 'dots', and if it does, you check if it is already in arr1, if not increment count and add element to arr1.
One way is to store element as key of an object, then get the count of the keys:
var arr = ["blue-dots", "blue", "red-dots", "orange-dots", "blue-dots"];
console.log(Object.keys(arr.reduce(function(o, x) {
if (x.indexOf('dots') != -1) {
o[x] = true;
}
return o
}, {})).length)
Try this something like this:
// Create a custom function
function countDots(array) {
var count = 0;
// Get and store each value, so they are not repeated if present.
var uniq_array = [];
array.forEach(function(value) {
if(uniq_array.indexOf(value) == -1) {
uniq_array.push(value);
// Add one to count if 'dots' word is present.
if(value.indexOf('dots') != -1) {
count += 1;
}
}
});
return count;
}
// This will print '3' on console
console.log( countDots(['blue-dots', 'blue', 'red-dots', 'orange-dots', 'blue-dots']) );
From this question, I got the getUnique function.
Array.prototype.getUnique = function(){
var u = {}, a = [];
for(var i = 0, l = this.length; i < l; ++i){
if(u.hasOwnProperty(this[i])) {
continue;
}
a.push(this[i]);
u[this[i]] = 1;
}
return a;
}
then you can add a function that counts ocurrences of a string inside an array of strings:
function getOcurrencesInStrings(targetString, arrayOfStrings){
var ocurrencesCount = 0;
for(var i = 0, arrayOfStrings.length; i++){
if(arrayOfStrings[i].indexOf(targetString) > -1){
ocurrencesCount++;
}
}
return ocurrencesCount;
}
then you just:
getOcurrencesInStrings('dots', initialArray.getUnique())
This will return the number you want.
It's not the smallest piece of code, but It's highly reusable.
var uniqueHolder = {};
var arr = ["blue-dots", "blue", "red-dots", "orange-dots", "blue-dots"];
arr.filter(function(item) {
return item.indexOf('dots') > -1;
})
.forEach(function(item) {
uniqueHolder[item] ? void(0) : uniqueHolder[item] = true;
});
console.log('Count: ' + Object.keys(uniqueHolder).length);
console.log('Values: ' + Object.keys(uniqueHolder));
Try this code,
arr = ["blue-dots", "blue", "red-dots", "orange-dots", "blue-dots"];
sample = [];
for (var i = 0; i < arr.length; i++) {
if ((arr[i].indexOf('dots') !== -1) && (sample.indexOf(arr[i]) === -1)){
sample.push(arr[i]);
}
}
alert(sample.length);
var arr = [ "blue-dots", "blue", "red-dots", "orange-dots", "blue-dots" ];
var fArr = []; // Empty array, which could replace arr after the filtering is done.
arr.forEach( function( v ) {
v.indexOf( "dots" ) > -1 && fArr.indexOf( v ) === -1 ? fArr.push( v ) : null;
// Filter if "dots" is in the string, and not already in the other array.
});
// Code for displaying result on page, not necessary to filter arr
document.querySelector( ".before" ).innerHTML = arr.join( ", " );
document.querySelector( ".after" ).innerHTML = fArr.join( ", " );
Before:
<pre class="before">
</pre>
After:
<pre class="after">
</pre>
To put this simply, it will loop through the array, and if dots is in the string, AND it doesn't already exist in fArr, it'll push it into fArr, otherwise it'll do nothing.
I'd separate the operations of string comparison and returning unique items, to make your code easier to test, read, and reuse.
var unique = function(a){
return a.length === 0 ? [] : [a[0]].concat(unique(a.filter(function(x){
return x !== a[0];
})));
};
var has = function(x){
return function(y){
return y.indexOf(x) !== -1;
};
};
var arr = ["blue-dots", "blue", "red-dots", "orange-dots", "blue-dots"];
var uniquedots = unique(arr.filter(has('dots')));
console.log(uniquedots);
console.log(uniquedots.length);

indexOf() when array-elements are objects (javascript)

For instance, a variable named arrayElements of type array contains:
[{id:1, value:5},{id:2, value:6},{id:3, value:7},{id:4, value:8}].
How do I get the position of the array element with id === 3(3rd element) in the arrayElements variable besides using loop?
thanks.
You have to loop at one point. But you can abstract it to look like you're not looping
function indexOfCallback(arr, callback, startIndex) {
if (typeof startIndex == 'undefined') {
startIndex = 0;
}
for(var i=startIndex; i < arr.length; i ++) {
if (callback(arr[i])) {
return i;
}
}
return -1;
}
var array = [{id:1, value:5},{id:2, value:6},{id:3, value:7},{id:4, value:8}];
// Search on id === 3
console.log(indexOfCallback(array, function(obj){
return obj.id === 3;
}));
// Search on value === 6
console.log(indexOfCallback(array, function(obj){
return obj.value === 6;
}));
As mentioned by Anthony, this is proposed for ECMAScript 6. Here's the more complete polyfill https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex
if (!Array.prototype.findIndex) {
Array.prototype.findIndex = function(predicate) {
if (this == null) {
throw new TypeError('Array.prototype.find called on null or undefined');
}
if (typeof predicate !== 'function') {
throw new TypeError('predicate must be a function');
}
var list = Object(this);
var length = list.length >>> 0;
var thisArg = arguments[1];
var value;
for (var i = 0; i < length; i++) {
value = list[i];
if (predicate.call(thisArg, value, i, list)) {
return i;
}
}
return -1;
};
}
console.log(array.findIndex(function(obj){
return obj.id === 3;
}));
arrayElements.map(o => o.id).indexOf(3);
Notes:
Possibly slower than a loop because transforms whole array prior to
search. But with high-level languages like Javascript, you never
know.
Infinitely more readable than a loop.
IE compatible (unlike findIndex as of 2017).
In an array like this, you cant access elements by id. So using a loop is the best solution you have. However, depending on your use case you could also consider using an object instead of an array for direct access.
var container = { 1: {id:1, value:5}, 2: {id:2, value:6}, 3: {id:3, value:7} }
const arrayElements = [
{ id: 1, value: 5 },
{ id: 2, value: 6 },
{ id: 3, value: 7 },
{ id: 4, value: 8 }
]
console.log(arrayElements.findIndex((item) => item.id === 3))
You can use an array filter but I think that you will get a better solution using a loop.
var array = [{id:1, value:5},{id:2, value:6},{id:3, value:7},{id:4, value:8}];
var result = array.filter(condition);
function condition(value, index){
if (value.id === 3) return index;
}
console.log(result);
I wrote a function for you that you can use get the job done, but it uses a loop:
var yourObjArray = [{id:1, value:5},{id:2, value:6},{id:3, value:7},{id:4, value:8}];
function objArrayIndex(objArray){
for(var i = 0; i < objArray.length; i++){
if(objArray[i]['id'] == 3){
return i;
}
}
return -1;
}
console.log(objArrayIndex(yourObjArray));

counting duplicate arrays within an array in javascript

I have an array of arrays as follows:
[[3, 4], [1, 2], [3, 4]]
I wish to create a new array of arrays that has no duplicates, and has a count of the number of occurrences of each element in the first array:
[[3,4,2], [1,2,1]]
here is what I have so far:
var alreadyAdded = 0;
dataset.forEach(function(data) {
From = data[0];
To = data[1];
index = 0;
newDataSet.forEach(function(newdata) {
newFrom = newData[0];
newTo = newData[1];
// check if the point we are looking for is already added to the new array
if ((From == newFrom) && (To == newTo)) {
// if it is, increment the count for that pair
var count = newData[2];
var newCount = count + 1;
newDataSet[index] = [newFrom, newTo, newCount];
test = "reached here";
alreadyAdded = 1;
}
index++;
});
// the pair was not already added to the new dataset, add it
if (alreadyAdded == 0) {
newDataSet.push([From, To, 1]);
}
// reset alreadyAdded variable
alreadyAdded = 0;
});
I am very new to Javascript, can someone help explain to me what I'm doing wrong? I'm sure there is a more concise way of doing this, however I wasn't able to find an example in javascript that dealt with duplicate array of arrays.
Depending on how large the dataset is that you're iterating over I'd be cautious of looping over it so many times. You can avoid having to do that by creating an 'index' for each element in the original dataset and then using it to reference the elements in your grouping. This is the approach that I took when I solved the problem. You can see it here on jsfiddle. I used Array.prototype.reduce to create an object literal which contained the grouping of elements from the original dataset. Then I iterated over it's keys to create the final grouping.
var dataSet = [[3,4], [1,2], [3,4]],
grouping = [],
counts,
keys,
current;
counts = dataSet.reduce(function(acc, elem) {
var key = elem[0] + ':' + elem[1];
if (!acc.hasOwnProperty(key)) {
acc[key] = {elem: elem, count: 0}
}
acc[key].count += 1;
return acc;
}, {});
keys = Object.keys(counts);
for (var i = 0, l = keys.length; i < l; i++) {
current = counts[keys[i]];
current.elem.push(current.count);
grouping.push(current.elem);
}
console.log(grouping);
Assuming order of sub array items matters, assuming that your sub arrays could be of variable length and could contain items other than numbers, here is a fairly generic way to approach the problem. Requires ECMA5 compatibility as it stands, but would not be hard to make it work on ECMA3.
Javascript
// Create shortcuts for prototype methods
var toClass = Object.prototype.toString.call.bind(Object.prototype.toString),
aSlice = Array.prototype.slice.call.bind(Array.prototype.slice);
// A generic deepEqual defined by commonjs
// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
function deepEqual(a, b) {
if (a === b) {
return true;
}
if (toClass(a) === '[object Date]' && toClass(b) === '[object Date]') {
return a.getTime() === b.getTime();
}
if (toClass(a) === '[object RegExp]' && toClass(b) === '[object RegExp]') {
return a.toString() === b.toString();
}
if (a && typeof a !== 'object' && b && typeof b !== 'object') {
return a == b;
}
if (a.prototype !== b.prototype) {
return false;
}
if (toClass(a) === '[object Arguments]') {
if (toClass(b) !== '[object Arguments]') {
return false;
}
return deepEqual(aSlice(a), aSlice(b));
}
var ka,
kb,
length,
index,
it;
try {
ka = Object.keys(a);
kb = Object.keys(b);
} catch (eDE) {
return false;
}
length = ka.length;
if (length !== kb.length) {
if (Array.isArray(a) && Array.isArray(b)) {
if (a.length !== b.length) {
return false;
}
} else {
return false;
}
} else {
ka.sort();
kb.sort();
for (index = 0; index < length; index += 1) {
if (ka[index] !== kb[index]) {
return false;
}
}
}
for (index = 0; index < length; index += 1) {
it = ka[index];
if (!deepEqual(a[it], b[it])) {
return false;
}
}
return true;
};
// Recursive function for counting arrays as specified
// a must be an array of arrays
// dupsArray is used to keep count when recursing
function countDups(a, dupsArray) {
dupsArray = Array.isArray(dupsArray) ? dupsArray : [];
var copy,
current,
count;
if (a.length) {
copy = a.slice();
current = copy.pop();
count = 1;
copy = copy.filter(function (item) {
var isEqual = deepEqual(current, item);
if (isEqual) {
count += 1;
}
return !isEqual;
});
current.push(count);
dupsArray.push(current);
if (copy.length) {
countDups(copy, dupsArray);
}
}
return dupsArray;
}
var x = [
[3, 4],
[1, 2],
[3, 4]
];
console.log(JSON.stringify(countDups(x)));
Output
[[3,4,2],[1,2,1]]
on jsFiddle
After fixing a typo I tried your solution in the debugger; it works!
Fixed the inner forEach-loop variable name to match case. Also some var-keywords added.
var alreadyAdded = 0;
dataset.forEach(function (data) {
var From = data[0];
var To = data[1];
var index = 0;
newDataSet.forEach(function (newData) {
var newFrom = newData[0];
var newTo = newData[1];
// check if the point we are looking for is already added to the new array
if ((From == newFrom) && (To == newTo)) {
// if it is, increment the count for that pair
var count = newData[2];
var newCount = count + 1;
newDataSet[index] = [newFrom, newTo, newCount];
test = "reached here";
alreadyAdded = 1;
}
index++;
});
// the pair was not already added to the new dataset, add it
if (alreadyAdded == 0) {
newDataSet.push([From, To, 1]);
}
// reset alreadyAdded variable
alreadyAdded = 0;
});
const x = [[3, 4], [1, 2], [3, 4]];
const with_duplicate_count = [
...x
.map(JSON.stringify)
.reduce( (acc, v) => acc.set(v, (acc.get(v) || 0) + 1), new Map() )
.entries()
].map(([k, v]) => JSON.parse(k).concat(v));
console.log(with_duplicate_count);

Removing duplicate element in an array [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Easiest way to find duplicate values in a JavaScript array
Javascript array sort and unique
I have the following array
var output = new array(7);
output[0]="Rose";
output[1]="India";
output[2]="Technologies";
output[3]="Rose";
output[4]="Ltd";
output[5]="India";
output[6]="Rose";
how can i remove the duplicate elements in above array.Is there any methods to do it?
You can write a function like this
function eliminateDuplicates(arr) {
var i,
len=arr.length,
out=[],
obj={};
for (i=0;i<len;i++) {
obj[arr[i]]=0;
}
for (i in obj) {
out.push(i);
}
return out;
}`
Check this here
Maybe more complex than you need but:
function array_unique (inputArr) {
// Removes duplicate values from array
var key = '',
tmp_arr2 = {},
val = '';
var __array_search = function (needle, haystack) {
var fkey = '';
for (fkey in haystack) {
if (haystack.hasOwnProperty(fkey)) {
if ((haystack[fkey] + '') === (needle + '')) {
return fkey;
}
}
}
return false;
};
for (key in inputArr) {
if (inputArr.hasOwnProperty(key)) {
val = inputArr[key];
if (false === __array_search(val, tmp_arr2)) {
tmp_arr2[key] = val;
}
}
}
return tmp_arr2;
}
Code taken from: http://phpjs.org/functions/array_unique:346
You can remove dups from an array by using a temporary hash table (using a javascript object) to keep track of which images you've already seen in the array. This works for array values that can be uniquely represented as a string (strings or numbers mostly), but not for objects.
function removeDups(array) {
var index = {};
// traverse array from end to start
// so removing the current item from the array
// doesn't mess up the traversal
for (var i = array.length - 1; i >= 0; i--) {
if (array[i] in index) {
// remove this item
array.splice(i, 1);
} else {
// add this value to index
index[array[i]] = true;
}
}
}
Here's a working example: http://jsfiddle.net/jfriend00/sVT7g/
For sizable arrays, using an object as a temporary index will be many times faster than a linear search of the array.
First of all, you'll want to use the array literal (var output = []) to declare your array. Second, you'll want to loop through your array and store all the values in a second array. If any value in the first array matches a value in the second array, delete it and continue looping.
Your code would look like this:
var output = [
"Rose",
"India",
"Technologies",
"Rose",
"Ltd",
"India",
"Rose"
]
var doubledOutput = [];
for(var i = 0; i < output.length; i++) {
var valueIsInArray = false;
for(var j = 0; j < doubledOutput.length; j++) {
if(doubledOutput[j] == output[i]) {
valueIsInArray = true;
}
}
if(valueIsInArray) {
output.splice(i--, 1);
} else {
doubledOutput.push(output[i]);
}
}
Please note, the above code is untested and may contain errors.

Categories