So I've this shopping cart, as JSON.
[{"tuote":{"id":"2","name":"Rengas 2","count":16,"price":"120.00"}},{"tuote":{"id":"1","name":"Rengas 6","count":"4","price":"25.00"}},{"tuote":{"id":"4","name":"Rengas 4","count":"4","price":"85.00"}}]
Formatted here.
So, I want to prevent from having the same value in there twice, and match them by their ids.
This is my current solution (buggy as a cockroach, doesn't really do the job), as the only time it works is when the matching value is first in the JSON string.
for (var i = 0; i < ostoskori.length; i++) {
if (ostoskori[i].tuote.id == tuoteID) {
addToExisting(tuoteID, tuoteMaara); //this doesn't matter, it works.
break //the loop should stop if addToExisting() runs
}
if (ostoskori[i].tuote.id != tuoteID) {
addNew(tuoteID, tuoteNimi, tuoteMaara, tuoteHinta); //this doesn't matter, it works.
//break
//adding break here will stop the loop,
//which prevents the addToExisting() function running
}
}
ostoskori is the json if you're wondering. As you can probably see, for each item the JSON has inside it, the more times addNew() will run.
So basically, if the JSON has a value with the same id as tuoteID, addToExisting() should run. If the JSON doesn't have a value same as tuoteID, run addNew().
But how?
You could use some to check if the id already exists. The beauty of some is:
If such an element is found, some immediately returns true.
If you're catering for older browsers there's a polyfill at the bottom of that page.
function hasId(data, id) {
return data.some(function (el) {
return el.tuote.id === id;
});
}
hasId(data, '4'); // true
hasId(data, '14'); // false
So:
if (hasId(data, '4')) {
addToExisting();
} else {
addNew();
}
Fiddle
Related
I have an input field where the user inputs their zip code which I then attempt to match to a zip code within an array. While the following works, I need it to actually show an alert dialog once saying that zip code wasn't found, however, it current pops up a lot even if the zip code is in the list.
Here's my snippet:
_zipcodeBtn.onclick = function(){
var userZip = _zipcode.value;
for (var i = 0; i < zipcode_list.length; i++) {
if (zipcode_list[i] === userZip) {
console.log('works');
break;
} else {
alert("repeating");
}
}
};
I want it to check if their zip is available without it also repeating the else statement multiple times. Whats the best way to prevent this?
There's an easier way to find an item in an array, by referencing the array's indexOf() method (docs).
if (zipcode_list.indexOf(userZip) != -1) {
//found - do something
} else
alert('Zip not found!');
As Angel Politis shows, you can also use includes() if you literally just want to know whether an item is in an array, not its actual position within it.
Sidenote: it's important to check against -1 when using indexOf() because it returns the index at which the search is found - or -1 if it's not. If the search is found at the first key, this is 0, and 0 is a falsy value, which can catch people out sometimes when they do things like this:
var arr = [1, 2, 3];
if (arr.indexOf(1))
alert('success');
else
alert('failed');
You'd think the success alert would fire here, but actually it'll be the failure alert, because indexOf() in this case returns 0, and 0 is a falsy value when it's interrogated in a condition.
There's no need to use a loop here. You can just say:
if (!zipcode_list.includes(userZip)) alert("Doesn't work!");
If you must use a loop, then just set a flag by default to false and then, if the zip is found set it to true. Then you can check it outside the loop:
/* Create a flag and set it by default to false. */
var found = false;
/* Loop */
for (var i = 0, l = zipcode_list.length; i < l; i++) {
if (zipcode_list[i] === userZip) {
/* Set the flag to true and stop the loop. */
found = true;
break;
}
}
/* Check whether the zip was found in the array. */
if (found) console.log("Works!");
else alert("Doesn't work!");
I am working on a problem. I do not know the right question to ask in order to solve this problem. I have gotten what seems to be the required results but the verification problem for the solution does not work. I am not sure if I am solving it correctly. Basically I am given an array and I have to filter out elements from that array by slicing certain ingredients.
question: "We only use the elements that the instruction tells us to. So, we need to create a slice of the given array of elements (taken from the beginning) to resemble only the elements we are using. If the instruction doesn't say anything, we only take the first element."
var hammerIngredients = ['iron', 'granite', 'copper'];
var spearIngredients = ['iron', 'granite', 'copper'];
var panIngredients = ['iron', 'granite', 'copper'];
take(hammerIngredients); // returns ['iron']
take(spearIngredients, 2); // returns ['iron', 'granite']
take(panIngredients, 3); // return ['iron', 'granite', 'copper']
"If the instruction says to use more than the elements listed, we use all the elements in the array. If the instruction says to use no elements, we return an empty array."
var plateIngredients = ['iron', 'granite', 'copper'];
take(plateIngredients, 0); // returns []
So I have tried to do the program and I have done the following. It appears to work, but when I try to verify it I get that it is invalid.
function take(ingredients, slicer) {
if (arguments.length === 1) {
slicer = 1;
}
if (ingredients === hammerIngredients){
return ingredients.slice(0, slicer);
} else if(ingredients === spearIngredients) {
return ingredients.slice(0,slicer);
} else if (ingredients === panIngredients) {
return ingredients.slice(0,slicer);
} else if (ingredients === plateIngredients) {
return ingredients.slice(0,slicer)
} else {
return;
}
}
And I have no idea why. Help please!
you have no logic for if the slicer parameter is 0, in which case you need to return an empty array.
Put this line in there and it should work, based on the requirements you gave:
if (slicer === 0) {
return [];
}
You code currently only works if one of those three exact arrays are used. Does the verification code create and use only those arrays?
Your code does not need to be tied to existing ingredient arrays. After setting the default slicer value you can just:
return ingredients.slice(0,slicer);
I am currently stuck with a javaScript for loop.
The situation is like this, in my program there is a function which returns true/ false value in every 200 ms.
The function, which I am currently trying to code, should obtain the value from the above function ( for the ease of reference, I would name it as, function1) and store it in an array.
I am trying to use a for loop to store those values in an 8 element array.
Shown below is my code,
function myFunction1(imagestatus) //
{
var statusArray = ["","","","","","","",""];
for (var i = 0; i <= statusArray.length - 1; i++)
{
statusArray[i] = imagestatus;
}
}
Now, during the first execution of the for loop, it will assign the 0th element of the array, true or false. And during the second execution also it will do the same which is no good.
The task I expect to do is, when the function1 returns its value to myFunction it must store it in the 0th element. Then when it returns again, if its as same as the value in 0th element, store it in the 1st element, if not same, then take a different action.
Start with an empty array:
var array[];
then use:
array.push(data);
To add each datum to the right end of the array.
Sounds like a number of things need to happen. First, you are asking for a callback function. Second, you need to move the status array to the global scope.
var statusArray = ["","","","","","","",""];
function myFunction1(imagestatus, callback, differentAction) //
{
var i = 0;
// if its as same as the value in 0th element,
while (statusArray[i]==imagestatus)
{
i++;
}
if (i<statusArray.length && i>0)
{
// store it in the 1st element
statusArray[i]=imagestatus;
if (typeof(callback)=="function")
{
callback();
return;
}
}
// if not same, then take a different action
if (typeof(differentAction)=="function")
{
differentAction();
return;
}
}
I'm trying to splice an array in order to delete an object from my array. I'm using angular-formly to display the forms and AngularJs and JQuery in order to handle the data.
The JQuery
$(document).on("click", ".delete-me", function () {
var id = $(this).parent().find('input, select, textarea').attr('id');
var splitid = id.split("_")[3];
angular.element(document.getElementById('View2Ctrl')).scope().removeField(splitid);
$(this).closest('.formly-field').remove();
});
The reason for the split and is that formly wraps an id like formly_1_input_textField-1_0.
The Angular Function
$scope.removeField = function (id) {
for(var i=0;i<$scope.formFields.length;i++){
if($scope.formFields[i].key == id){
$scope.formFields.splice(id, 1);
console.log($scope.formFields.length);
$scope.currentId = i;
}
}
};
The console log is displaying the actual length of the array however I have {{formFields.length}} on the template and it does not update, as well as {{formFields}} still showing the data in the array. I suspect that JQuery updating the DOM isn't being watched by Angular and have tried calling $scope.$apply() manually to no avail.
You have a couple of logic errors in your function:
When you remove an item from the array, you increase i anyway, which means you'll miss out the next item if it's a match.
You're using id instead of i in the splice
That second one is probably the culprit, but once you'd fixed that, the first would have bitten you (unless the id values are unique, as the name implies; in which case, you should probably terminate the loop when you find it).
Updates:
$scope.removeField = function (id) {
var i=0;
while (i<$scope.formFields.length){ // Use a while loop
if($scope.formFields[i].key == id){
$scope.formFields.splice(i, 1); // Use i, not id
console.log($scope.formFields.length);
$scope.currentId = i;
// DON'T increment i here, you've removed the element
// Or if IDs are unique, just terminate the loop
} else {
++i;
}
}
};
For some reason in the code below the currentRow.cells returns {}. How can I check for that? I do not want to execute lines if the currentRow.cells returns {}.
currentRow = document.createElement("TR");
if(currentRow.cells.length > 0) { .. do something }
UPDATE 1:
All I want is to check for empty object. if the currentRow.cells is an empty object then do nothing.
I always get an object of type HTMLCollection.
You should be able to then check the length of the collection using code like this:
if(currentRow.cells.length != 0) {
//row and cells exist, work with them
}
jQuery has a helper method called $.isEmptyObject().
Their code for this is simple:
function isEmptyObject( obj ) {
for ( var name in obj ) {
return false;
}
return true;
}
If you don't want to use the whole jQuery library, you can snag this method and drop it somewhere in your own code base!
To answer your question in the title:
function is_empty(obj) {
for(var i in obj) {
if(obj.hasOwnProperty(i))
return false;
}
return true;
}
alert(is_empty({})); // true
currentRow is a <tr> (or a HTMLTableRowElement), and currentRow.cells is a HTMLCollection (not an Array ([]) or an object ({})).
If currentRow.cells is undefined, that means that current row isn't a <tr>, it's another element.
To check if a DOM element is empty, you can use childNodes (this will never be undefined).
if(currentRow.childNodes.length === 0){
// empty
}
else{
// not empty
}
Edit: Better yet, you can use hasChildNodes.
if(!currentRow.hasChildNodes()){
// empty
}
else{
// not empty
}
cells property isn't available in <tr> on IE8 and below. A workout is to use childNodes as suggested above. The following code checks if cells is undefined:
var currentRow = document.createElement("TR");
if (typeof currentRow.cells === "undefined") {
// use currentRow.childNodes
}
else {
// use currentRow.cells
}