I am creating a project using Angular. During the development, I am facing a problem when pushing values to my array. My requirement is that I want to push the value to the array unless the value already exists in the array. If it already exists, then simply replace that value with newer value.
This is my code, which is currently not working:
var obj = {
question_id: "1",
id: "2",
"question": "This is a test"
};
This is the object that I want to push:
this.selectedOptions = [];
if (!this.selectedOptions.some(function(entry) { return entry.question_id === category.question_id;})) {
this.selectedOptions.push(category);
}
Your code will push the item to the array, but it won't replace an existing item.
I'm assuming that its an array of objects, given the entry.question_id part.
What you need is to check if the object exists in the array, and update or push it accordingly. The findIndex method will return the object index, if it exists in the array, or -1 if not.
const entryIndex = this.selectedOptions.findIndex(entry => entry.question_id === category.question_id);
if (entryIndex > -1) {
this.selectedOptions[entryIndex] = category;
} else {
this.selectedOptions.push(category);
}
You could find the index for update or push something new.
let index = this.selectedOptions.findIndex(function (entry) {
return entry.question_id === category.question_id;
});
if (index === -1) {
this.selectedOptions.push(category);
} else {
this.selectedOptions[index].someKey = 'someValue';
}
Try this:
function customUpsert(arr, data) {
const index = arr.findIndex((e) => e.id === data.id);
if (index === -1) {
arr.push(data);
} else {
arr[index] = data;
}
}
Following funcntion checks if "oldVal" exists and replace it with the "newVal" if it does.
var selectedOptions = [1, 2, 3];
function replaceOrAppend(oldVal, newVal) {
let idx = selectedOptions.indexOf(oldVal);
if (idx < 0)
selectedOptions.push(newVal)
else
selectedOptions[idx] = newVal;
}
replaceOrAppend(1, 100);
replaceOrAppend(10, 200);
console.log(selectedOptions);
Related
I'm building up an array of socket.ids and trying to get a 'temporary' id for them by getting the array index as being the 'temporary' ID.
I am currently building my array as follows:
let serving_point_key = serving_points.indexOf(socket.id);
if (serving_point_key === -1) {
serving_points.push(socket.id);
serving_point_key = serving_points.indexOf(socket.id);
}
let serving_point_id = serving_point_key + 1;
and I am removing the items from the array as:
let serving_point_key = serving_points.indexOf(socket.id);
if (serving_point_key !== -1) {
serving_points.splice(serving_point_key, 1);
}
The issue I'm having is that if there is 3 items in the array, and I remove the second for example, the index of the third item is now 1 less, therefore the logic of using indexOf to get an 'temporary' ID is flawed when I try and get the "ID" for the socket user as it's changed as soon as I remove an item before it in the array?
Is there anyway to keep the index when I push to an array, so that the index is kept when removing? maybe using a multi dimensional array? or would it be best to use objects?
Any help or advice would be greatly appreciated.
I've updated the logic to push an object to the array and store the ID.
let serving_point_key = serving_points?.findIndex(sp => sp.socket_id === socket.id);
if (serving_point_key === -1) {
let id = null;
if (serving_points.length === 0) {
id = 1;
} else {
for( var i = 0; i < serving_points.length; i++ ) {
let id_exists = (serving_points?.findIndex(sp => sp.id === (i + 1)) !== -1);
if (id_exists === false) {
id = (i + 1);
}
}
console.log(id);
if (id === null) {
id = serving_points.length + 1;
}
}
let sp_data = {
'id': id,
'socket_id': socket.id
}
serving_points.push(sp_data);
serving_point_key = serving_points?.findIndex(sp => sp.socket_id === socket.id);
}
let serving_point_id = serving_points[serving_point_key].id;
I know the title is not clear enough but I will try to explain more here.
I have a flatlist that I have to select multi Items and create a string value containing the item's id and item's price that I have to send to server.
this is my approach: (it work fine)
selectItem = data => {
let test = 130;
if (data.Unites < test) {
data.Etat = 0
console.warn('points insufisants');
} else {
data.isSelect = !data.isSelect;
data.selectedClass = data.isSelect ? StylesGift.validChek : StylesGift.inValidChek;
const newItem = {
idCadeau: data.idCadeau,
Unites: data.Unites,
};
if (data.isSelect) {
const index = this.state.paramsSend.indexOf([newItem]);
this.setState({
paramsSend: this.state.paramsSend.concat([newItem]),
}, () => {
let str = this.state.paramsSend.map(v => Object.values(v).join('_')).join(',')
this.setState({
params: str,
});
});
}else if (data.isSelect === false) {
const index = this.state.paramsSend.indexOf([newItem]);
if (index > -1) {
array.splice(index, 1);
let str = this.state.paramsSend.map(v => Object.values(v).join('_')).join(',')
this.setState({
params: str,
});
}
console.log('looog' + this.state.paramsSend);
}
}
this.setState({changed: !this.state.changer})
};
My probleme is whene I deselect an item I can't remove the item's id and price with this code:
else if (data.isSelect === false) {
const index = this.state.paramsSend.indexOf([newItem]); <-- =-1
if (index > -1) {
this.state.paramsSend.splice(index, 1);
let str=this.state.paramsSend.map(v=>Object.values(v).join('_')).join(',')
this.setState({
params: str,
});
}
console.log('looog' + this.state.paramsSend);
}
any suggestion please ? indexOf return -1
I don't know why
const index = this.state.paramsSend.indexOf([newItem]);
console.warn('index ' + index);
console.warn('from this ' +JSON.stringify(this.state.paramsSend));
console.warn('remove this ' + JSON.stringify(newItem));
newItem is already in paramsSend but it return -1 !
you have 2 issues:
don't call indexOf with an array, but just with the element you're looking for: const index = this.state.paramsSend.indexOf(newItem);
indexOf(item) called on an array of objects works only if item argument is an actual object in the array, not a copy. i.e. this won't work: const index = this.state.paramsSend.indexOf({ idCadeau: 5, Unites: 180 }); even though an identical object exists in the array
So this should solve both issues:
const index = this.state.paramsSend.findIndex(item => item.idCadeau === newItem.idCadeau)
if (index > -1) {
// good!
}
Your code isn't very clear, but try to use the filter function.
It push in a array all elements matching the condition
const newDataArray = data.filter(elem => elem.idCadeau !== newItem.idCadeau)
So here, you have a new array with all the elements wich are not the same than your newItem
var vm = this;
vm.usableDeposits = [];
for (var i = 0; i < billableChargeCodes.length; i++) {
var deposits = usableDeposits.filter(function(ud) {
return ud.billinggroupuid == billableChargeCodes[i].billinggroupuid ||
ud.billinggroupuid == billableChargeCodes[i].billingsubgroupuid ||
ud.departmentuid == billableChargeCodes[i].departmentuid ||
!ud.entypeuid ||
ud.entypeuid == entypeuid
})
for (var i = 0; i < deposits.length; i++) {
var depositid = deposits[i]._id;
first time, vm.usableDeposits[] is empty. I have to check deposits[i]._id exists in vm.usableDeposits[] or not. How to check vm.usableDeposits[] empty array _id with deposits[i]._id? if id not exists in vm.usableDeposits[], then i want to push the element into vm.usableDeposits[]
You can simply use the indexOf operator in JavaScript to check if a value exists in the array or not. It returns -1 if the value is not in the array, else, it returns the index of the element in the array.
The syntax goes like this -
if(myArray.indexOf(value) !== -1) {
// do this
} else {
// do that
}
Hope this helps.
You can use .some
deposits.some(o=> vm.usableDeposits.indexOf(o.id))
to check if the ID in deposits array is in vm.usableDeposits. .some will return true if condition is true and false otherwise
$scope.findIndexInData = function(data, property, value) {
var result = -1;
if((!!data) && (!!property) && (!!value)){
data.some(function (item, i) {
if (item[property] === value) {
result = i;
return true;
}
});
}
return result;
}
Pass on the array as the First Element. Property as second element and value you are looking in that array.
Example:
array = [{id:"1234",name:"abc"}, {id:"4567",name"xyz"}]
So you need to call:
index = $scope.findIndexInData(array , 'id' , 4567)
I am dealing with a fairly complex object. It contains 2 arrays, which contain 3 arrays each of objects:
I'm trying to delete one of the history: Array[2] if one of the objects in it has username: null.
var resultsArray = result.history;
var arrayCounter = 0;
resultsArray.forEach(function(item) {
item.forEach(function(innerItem) {
if (innerItem.username == null) {
resultsArray.splice(arrayCounter,1);
};
});
arrayCounter++;
});
Looking through answers it's recommended to do something like:
resultsArray.splice(arrayCounter,1);
This isn't working in this situation because more than one of the objects could have username == null and in that case it will delete multiple history objects, not just the one that I want.
How do I remove only the one specific history array index if username == null?
splice is evil. I think using immutable array methods like filter might be easier to reason about:
x.history =
x.history.filter(function (h) {
return !h.some(function (item) {
return item.username === null
})
})
Go through all the histories, and do not include them in the filter if they have a username that is null.
My understanding was that you only want to delete the first outer array that has an inner array that has an object with a null username. Heres one solution closest to your current form:
var resultsArray = result.history;
var arrayCounter = 0;
var foundFirstMatch = false;
resultsArray.forEach(function(item) {
if (!foundFirstMatch) {
item.forEach(function(innerItem) {
if (innerItem.username == null && !foundFirstMatch) {
foundFirstMatch = true;
};
});
arrayCounter++;
}
});
if (foundFirstMatch > 0)
resultsArray.splice(arrayCounter, 1);
Other syntax:
var resultsArray = result.history;
var outerNdx;
var innerNdx;
var foundMatch = false;
for (outerNdx = 0; !foundMatch && outerNdx < resultsArray.length; outerNdx++) {
for (innerNdx = 0; !foundMatch && innerNdx < resultsArray[outerNdx].length; innerNdx++) {
if (resultsArray[outerNdx][innerNdx].username == null) {
foundMatch = true;
}
}
}
if (foundMatch)
resultsArray.splice(outerNdx, 1);
Update - here's how I'd do it now, without lodash:
thing.history.forEach((arr, i) => {
thing.history[i] = arr.filter( (x) => x.username !== null );
});
Previous answer:
I'd use lodash like this:
_.each(thing.history, function(array, k){
thing.history[k] = _.filter(array, function(v){
return v.username !== null;
})
});
Here's a jsfiddle:
https://jsfiddle.net/mckinleymedia/n4sjjkwn/2/
You should write something like this:
var resultsArray = result.history.filter(function(item){
return !item.some(function(inner){ return inner.username==null; });
});
The foreach loop cant break in this way but a regular for loop can. This is working:
result.history.forEach(function(item) {
loop2:
for (var i = 0; i < item.length; i++) {
var innerItem = item[i];
console.log(innerItem);
break loop2;
}
});
I implemented a function that creates a duplicate-free version of an array, but it doesn't work for array of objects. I don't understand and I can't find information how to fix it.
My function:
function uniq(array) {
var length = array.length;
if (!length) {
return;
}
var index = 0;
var result = [];
while (index < length) {
var current = array[index];
if (result.indexOf(current) < 0) {
result.push(current);
}
index++;
}
return result;
}
Example:
var my_data = [
{
"first_name":"Bob",
"last_name":"Napkin"
},
{
"first_name":"Billy",
"last_name":"Joe"
},
{
"first_name":"Billy",
"last_name":"Joe",
}
]
uniq([1, 1, 2, 3]) // => [1, 2, 3]
uniq(my_data) // => [ { "first_name":"Bob", "last_name":"Napkin" }, { "first_name":"Billy", "last_name":"Joe" }, { "first_name":"Billy", "last_name":"Joe" } ]
Do you know someone how to creates a duplicate-free version of array of objects?
indexOf() in javascript does not perform a deep comparison of objects. On top of that, any two objects that are created will never be "equal" to each other. If you do:
var a = {};
var b = {};
a == b; //false
a === b; //false
You need to perform a deep comparison against all values (if that's even what you're looking to do, because there could be other equalities you're looking for). I won't go into how to do a deep comparison because, well, Google.
A solution if the objects are not huge, the array doesn't have a huge amount of elements and if the objects don't contain reference loops is to use JSON.stringify to decide if two objects are equal...
function uniq(A) {
var seen = {};
var result = [];
A.forEach(function(x) {
var str = "" + JSON.stringify(x);
if (!seen[str]) {
seen[str] = 1;
result.push(x);
}
});
return result;
}
Since these objects are simply used for data storage (i.e. they don't have methods or prototype extensions and such applied to them), I might suggest serializing and hashing each object in the array and storing the hashes in an object for determination of uniqueness. Now the question is which hashing function to use. There are a number of md5 and SHA-256 implementations available (search StackOverflow for this). My example will just assume the existence of a hash function called hashFunction().
function uniqArrayObjects(array) {
// make sure we have an array
if(Array.isArray(array) === false) {
console.log('Doh! No array passed.');
return null;
}
var length = array.length;
// you can return input array if it has 0 or 1 items in it
// it is already unique
if (length === 0 || length === 1) {
return array;
}
// object for storing hashes
var hashTable = {};
// filter and return the array
return array.filter(function(obj) {
var json = JSON.stringify(obj);
var hash = hashFunction(json);
if (typeof hashTable[hash] === undefined) {
// this item doesn't exist in hash table yet
// add to hash table and return true to add this to filtered result
hashTable[hash] = 1; // value doesn't matter here
return true;
} else {
return false;
}
});
}