Splice not being called in loop, id not found in array - javascript

I'm trying to splice an array by parameter given from an onClick element like deleteFavourite(2). Three console logs show: id (2), fired message, and saved message, but the spliced message is ignored. Why is it not hitting the if?
Function:
deleteFavourite: function (id) {
console.log(id);
console.log("fired");
var array = this.favourites;
for (var i = 0; i < array.length; i++) {
if (array[i] === id) {
array.splice(i, 1);
console.log("spliced");
}
}
this.save();
console.log("saved");
}
The array is outputted like this in Chrome
Array(3)
0: {id: 0, title: "↵Page 0 ", url: "/page-0/"}
1: {id: 1, title: "↵Social media ", url: "/social-media/"}
2: {id: 2, title: "↵Get involved ", url: "/get-involved/"}
length: 3
__proto__: Array(0)

Because you're working with an array containing plain objects, so your control should be:
deleteFavourite: function (id) {
console.log(id);
console.log("fired");
var array = this.favourites;
for (var i = 0; i < array.length; i++) {
if (array[i].id === id) {
array.splice(i, 1);
console.log("spliced");
}
}
this.save();
console.log("saved");
}
Indeed, you want to compare the id inside the array with the int you passed as a parameter.
Otherwise, you're comparing an object (the array[i] is an object containing 3 attributes) to an int, which will never result as true.

I guess you don't need to loop your array for that. To make it work as it is try to not compare in if statement the whole section of array to a number but only iteration of your array with a number. In my opinion this should look like this first check if element of array exist then slice it.
if (array[id]) {
array.splice(id, 1);
console.log("spliced");
}

Try:
deleteFavourite: function (id) {
console.log("deleteFavourite: ", id);
var array = this.favourites;
for (var i = 0; i < array.length; i++) {
if (array[i].id === id) { // <---- MY CHANGE
array.splice(i, 1);
console.log("spliced");
}
}
this.save();
console.log("saved");
}
You should have used array[i].id since the index of the items in your array does not match the actual id index.
Using ES2015 findIndex:
deleteFavourite: function (id) {
var array = this.favourites,
index = array .findIndex(item => item.id == id);
if( index > -1 ){
array.splice(index, 1);
this.save();
}
}

Related

Remove the duplicate values before pushing into an array

It's visible in the image that the array[0] and array[3], array1 and array[4] are same. I was checking why the values are duplicating but I failed. So thought to just remove if any duplicate values exists. I need to remove it from
$scope.arr array itself.
Code:
$scope.arr = [];
planReq.then(function (callplanList) {
$scope.callplanList = callplanList.data.callplans;
//console.log($scope.callplanList);
for(var i = 0; i < $scope.planMapping.length; i++){
//console.log($scope.planMapping[i].PlanScode);
for(var j = 0; j < $scope.callplanList.length; j++){
if(($scope.planMapping[i].PlanScode == $scope.callplanList[j].un_s_code) && ($scope.callplanList[j].offer_type == "REC")){
//console.log($scope.devicesList);
for(var a = 0; a < $scope.callplanList[j].upfront_cost.length; a++){
if($scope.callplanList[j].upfront_cost[a].upfront != ""){
//console.log($scope.callplanList[j].upfront_cost[a].handsetClass);
for(var k = 0; k < $scope.devicesList.length; k++){
if($scope.callplanList[j].upfront_cost[a].handsetClass == $scope.devicesList[k].device_class.toLowerCase()){
$scope.arr.push($scope.devicesList[k]);
}
}
}
}
}
}
}
console.log($scope.arr);
});
Any help would be appreciated.
Make use of filter.
Here is a simple filter, to remove duplicates from an array
Array.filter(function(elem, index, self){ return self.indexOf(elem) == index })
In your case it will be
$scope.arr = $scope.arr.filter(function(elem, index, self){
return self.indexOf(elem) == index
});
method 1:
var list =[{name:"a",age:2}, {name:"b",age:4}, {name:"c",age:6}, {name:"a",age:2}]
var arr = list.filter((elem, index, self) => self.findIndex(
(t) => {return (t.name === elem.name && t.age === elem.age)}) === index)
it return unique array based on all the properties
method 2:
If you want to remove duplicate elements from an array use the following function. Here the args are:
myArr: contain array ob objects
prop: the property of object by which the array elements should be removed
function removeDuplicates(myArr, prop) {
return myArr.filter((obj, pos, arr) => {
return arr.map(mapObj => mapObj[prop]).indexOf(obj[prop]) === pos;
});
}
It will remove the duplicates based on the elements property and return the array with unique elemnts.
ngRepeat uses $watchCollection to detect changes in the collection. When a change happens, ngRepeat then makes the corresponding changes to the DOM:
When an item is added, a new instance of the template is added to the DOM.
When an item is removed, its template instance is removed from the DOM.
When items are reordered, their respective templates are reordered in the DOM.
To minimize creation of DOM elements, ngRepeat uses a function to "keep track" of all items in the collection and their corresponding DOM elements. For example, if an item is added to the collection, ngRepeat will know that all other items already have DOM elements, and will not re-render them.
The default tracking function (which tracks items by their identity) does not allow duplicate items in arrays. This is because when there are duplicates, it is not possible to maintain a one-to-one mapping between collection items and DOM elements.
If you do need to repeat duplicate items, you can substitute the default tracking behavior with your own using the track by expression.
so you can do like this :
<div ng-repeat="n in [42, 42, 43, 43] track by $index">
{{n}}
</div>
If you want to remove duplicates from array :
function UniqueArraybyId(collection, keyname) {
var output = [],
keys = [];
angular.forEach(collection, function(item) {
var key = item[keyname];
if(keys.indexOf(key) === -1) {
keys.push(key);
output.push(item);
}
});
return output;
};
planReq.then(function (callplanList) {
$scope.callplanList = callplanList.data.callplans;
//console.log($scope.callplanList);
for(var i = 0; i < $scope.planMapping.length; i++){
//console.log($scope.planMapping[i].PlanScode);
for(var j = 0; j < $scope.callplanList.length; j++){
if(($scope.planMapping[i].PlanScode == $scope.callplanList[j].un_s_code) && ($scope.callplanList[j].offer_type == "REC")){
//console.log($scope.devicesList);
for(var a = 0; a < $scope.callplanList[j].upfront_cost.length; a++){
if($scope.callplanList[j].upfront_cost[a].upfront != ""){
//console.log($scope.callplanList[j].upfront_cost[a].handsetClass);
for(var k = 0; k < $scope.devicesList.length; k++){
if($scope.callplanList[j].upfront_cost[a].handsetClass == $scope.devicesList[k].device_class.toLowerCase()){
$scope.arr.push($scope.devicesList[k]);
}
}
}
}
}
}
}
$scope.arr = UniqueArraybyId($scope.arr ,"sub_family"); //you have to pass the key name
console.log($scope.arr);
})
Here is the fiddle :
function UniqueArraybyId(collection, keyname) {
var output = [],
keys = [];
angular.forEach(collection, function(item) {
var key = item[keyname];
if(keys.indexOf(key) === -1) {
keys.push(key);
output.push(item);
}
});
return output;
};
function test () {
var arr =[{sub_family:'j3 (2016)'},{sub_family:'j3 (2016)'},{sub_family:'j3 (2017)'}]
arr= UniqueArraybyId(arr ,"sub_family"); //you have to pass the key name
console.log(arr);
};
test();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
I think this is the best way to remove duplicates from an Array. Note that this requires ES6.
arr = Array.from(new Set(arr));
Example:
var arr = [0, 1, 1, 1, 1, 2, 3, 4, 3, 4, 2, 2, 4];
console.log(arr.join(", "));
arr = Array.from(new Set(arr));
console.log(arr.join(", "));

Decrement ID in JSON array after deletion

I have an array stored in my local storage. It is dynamic. I'm storing the data along with an ID which gets incremented after every entry. User has an option of deleting, hence, I'm supposed to remove the corresponding element from the array. But, I want the ID to remain in ascending order. Ex:
var jsonObj = [{'id':'1','name':'Ray','email':'ray#gmail.com'},
{'id':'2','name':'Steve','email':'steve#gmail.com'},
{'id':'3','name':'Albert','email':'albert#gmail.com'},
{'id':'4','name':'Christopher','email':'chris#gmail.com'}]
I'm creating HTML divs for the above array. In case, Steve deletes his details, I want the array to be like:
var jsonObj = [{"id":1,"name":"Ray","email":"ray#gmail.com"},
{"id":2,"name":"Albert","email":'albert#gmail.com"},
{"id":3,"name":"Christopher","email":"chris#gmail.com"}]
The following code doesn't work accordingly.
for (var i=0; i<jsonObj.length; i++) {
//delete function is working fine.
jsonObj[i].id--;
break;
}
You could just iterate from the given index and decrement the id property.
function deleteItem(i) {
array.splice(i, 1);
while (i < array.length) {
array[i].id--;
i++;
}
}
var array = [{ id: '1', name: 'Ray', email :'ray#gmail.com'}, { id: '2', name: 'Steve', email: 'steve#gmail.com' }, { id: '3', name: 'Albert', email: 'albert#gmail.com' }, { id: '4', name: 'Christopher', email: 'chris#gmail.com' }];
deleteItem(1);
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
If you start from 0, then you do not even need the ID
Ray is the 0th element, Christopher is 3rd
delete Albert and Christopher is 2nd
var jsObj = [{'name':'Ray','email':'ray#gmail.com'},
{'name':'Steve','email':'steve#gmail.com'},
{'name':'Albert','email':'albert#gmail.com'},
{'name':'Christopher','email':'chris#gmail.com'}]
for (var i=0;i<jsObj.length;i++) {
document.write("<br>ID"+(i+1)+": "+jsObj[i].name)
}
document.write("<hr/>");
jsObj.splice(2, 1); // Bye bye Albert
for (var i=0;i<jsObj.length;i++) {
document.write("<br>ID"+(i+1)+": "+jsObj[i].name)
}
More information
Reindex javascript array / object after removing a key
You just declare a new variable in your for loop which you will increment it and you assign this value as their id
for (var i=0, id=1; i<jsonObj.length; i++, id++) {
var jsonObj = [{'id':'1','name':'Ray','email':'ray#gmail.com'},
{'id':'2','name':'Steve','email':'steve#gmail.com'},
{'id':'3','name':'Albert','email':'albert#gmail.com'},
{'id':'4','name':'Christopher','email':'chris#gmail.com'}];
console.log(jsonObj);
jsonObj.splice(1, 1);
for (var i=0, id=1; i<jsonObj.length; i++, id++) {
jsonObj[i].id = id;
}
console.log(jsonObj);
a very simplistic approach could be:
// the index of the deleted element
const delIndex = 2;
// reindex all entries starting from deleted one
for (var i=delIndex+1; i<jsonObj.length; i++) {
jsonObj[i].id = i + 1;
}
The id basically corresponds with the array index anyway. So instead of trying to compute the id anew, we can just overwrite it with the respective index (+1 as you start with one and not zero like array indices).
for your requirements you have to use the splice method in the javascript
array.splice(index_you_wantto_delete,count)
ex:-jsonObj.splice(1,1);
The splice() method adds/removes items to/from an array,
Here is a verbose solution explaining the process step by step
1- Delete the element
2 - Update the indexes if the element was found and deleted
/**
*
* #param array list Your list
* #param int elementID The id of the element you want to remove
* #returns list The list with the element removed and the indexes rearanged
*/
var deleteElement = function (list, elementID) {
var removedIndex = false;
for (var index = 0; index < list.length; index++) {
if (list[index]['id'] === elementID) {
list.slice(index, 1);
removedIndex = index;
break;
}
}
if (removedIndex !== false) {
//Get last id
var lastElement = (removedIndex === 0) ? null : list[removedIndex - 1];
// Set to 0 if the first element was removed
var lastID = (lastElement === null) ? 0 : lastElement.id;
for (var i = removedIndex; i < list.length; i++) {
list[i].id = ++lastID;
}
}
return list;
};
Try the below method. Hope it works !!
// index of the deleted item
var itemDeleted = 2;
// create a for loop from deleted index till last
for (var i = itemDeleted-1; i < jsonObj.length; i++) {
jsonObj[i].id = i+1;
}
You can do in pure js by using map
const jsonObj = [{
'name': 'Ray',
'email': 'ray#gmail.com'
},
{
'name': 'Steve',
'email': 'steve#gmail.com'
},
{
'name': 'Albert',
'email': 'albert#gmail.com'
},
{
'name': 'Christopher',
'email': 'chris#gmail.com'
}
];
jsonObj.splice(1, 1);
const newObj = jsonObj.map((c, i) => ({
name: c.name,
email: c.email,
id: i + 1
}));
console.log(newObj);
Get the deleted index and assign it to the i value of for loop
for (var i=deletedIndex; i<jsonObj.length; i++) {
jsonObj[i].id--;
}

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;
}

Deleting Element After Pushing

If I have an array where I am pushing certain elements to a second array- how can I delete those elements from the first array after pushing them to the second? Here is sample code:
for(var a = 0; a < arr.length; a+=1){
if(arr[a].length == 4){
other.push(arr[a]);
}
}
In other words, I know longer want elements arr[a] to be in arr if they have been pushed to other.
Just do a splice on that original array index to remove that element if you no longer require it.
for(var a = 0; a < arr.length;){
if(arr[a].length == 4){
other.push(arr[a]);
arr.splice(a, 1);
}
else {
a += 1;
}
}
This seems fine:
for(var a = 0, length=arr.length; a < length; a++){
if(arr[a].length == 4){
other.push(arr[a]);
arr.splice(a,1);
}
}
Write a function which takes an input array, and a function to determine if an element should be moved. It returns a two-element array, containing the modified input, and the new array into which elements have been extracted.
function extractIf(array, condition) {
return [
array.filter(not(condition)),
array.filter( condition)
];
}
// Specify which elements are to be extracted/moved.
function condition(elt) { return elt.length === 4; }
// Little helper function to invert a function.
function not(fn) { return function() { return !fn.apply(this, arguments); }; }
Invoke this as:
var results = extractIf(arr, condition);
arr = results[0];
other = results[1];
underscore solution
If you are willing to use underscore, you could group the input by the true/false value of the condition:
var groups = _.groupBy(arr, function(elt) { return elt.length === 4; })
Your original array with the elements removed will be in groups.false, and the other array in groups.true.

find the object index using id in json

I have a json that contains many objects:
[Object, Object, Object, ... ]
Inside each object there is an object number and an id:
0: Object
id: "theObjectImLookingFor"
...
How can I find the object number (0) using the id "theObjectImLookingFor" in javascript?
Try this:
function someFunc(){
var objArr = [Object, Object, Object, ... ];
for(var i = 0; i < objArr.length; i++){
if(objArr[i].id == "theObjectImLookingFor")
return i;
}
return "No value matched";
}
This assumes there's only one property with a numeric name. This is a very strange way to store something you want to be able to look up. Why not give each object an obj_number property?
function find_object(json, str) {
for (var i = 0; i < json.length; i++) {
if (json[i].id == str) {
for (var key in json[i]) {
if (IsNumeric(key)) {
return key;
}
}
}
}
return false; // Not found
}

Categories

Resources