1

Sorry for the maybe misleading title.

I have two arrays, one contains the defaults and another one contains products.

What I am trying to do is compare the two so that you can add/remove as many products as you like, but you can't have less products as the default.

Lets say

default = [1,2]

products = [1,1,1,1,2,2,2,3,4,5,6,7,8,9]

this should work.

But you can't have something like this:

default = [1,2]

products = [2,2,2,3,4,5,6,7,8,9]

because at least the same amount of products in the default array is required, and in the last example, 1 is not included in the products array.

I am using this to compare the two arrays:

Array.prototype.containsArray = function ( array /*, index, last*/ ) {

    if( arguments[1] ) {
        var index = arguments[1], last = arguments[2];
    } else {
        var index = 0, last = 0; this.sort(); array.sort();
    };

    return index == array.length
        || ( last = this.indexOf( array[index], last ) ) > -1
        && this.containsArray( array, ++index, ++last );

};

arr1.containsArray( arr2 )

which works. In my function (the one used to add/remove products) I tried to have the check like this:

removeDeviceToZone = function(zone, ID) {
  if (products.containsArray(default) {
    return products = removeFromArray(products, ID);
  }
};

but the problem is that at the time the check is executed, the array is still correct, but it won't be anymore as soon as a product is removed. What's the best way to have the check prevent what the array will be after removing the item without really removing it yet? Is it even possible? is it the best approach to do this? thanks

6
  • Both the array contains only the product ids Commented Jul 26, 2017 at 9:49
  • asking same before it removed, and prevent to make remove if is not. There is any code that makes the remove? Commented Jul 26, 2017 at 9:49
  • default is a JS keyword. rename the argument Commented Jul 26, 2017 at 9:49
  • @VarunSharma default is only here for explain, I am not using default as a name in my code Commented Jul 26, 2017 at 9:49
  • @ÁlvaroTouzón is a simple array.splice(id, 1) Commented Jul 26, 2017 at 9:50

3 Answers 3

2

You should use every function which accepts a callback provided method applied on every item in the array.

The every() method tests whether all elements in the array pass the test implemented by the provided function.

function containsArray(defaultArray, products){
    return defaultArray.every(function(item){
      return products.indexOf(item)!=-1;
    });
}
let defaultArray = [1,2]
let products = [1,1,1,1,2,2,2,3,4,5,6,7,8,9];
let products2=[2,2,2,3,4,5,6,7,8,9];
let contains=containsArray(defaultArray,products);
let contains2=containsArray(defaultArray,products2);
console.log(products.toString()+'->'+contains);
console.log(products2.toString()+'->'+contains2);

When you delete items you should check if the containsArray keeps to be true. In the other words you have to check if the containsArray function returns true after remove element.If yes, return products. Otherwise, return the old products array.

removeDeviceToZone = function(zone, ID) {
   let productsCopy=products;
   let products=removeFromArray(products, ID);
   if (containsArray(default,products) && containsArray(default,productsCopy) {         
      return products;
   }
   else
      return productsCopy;
};
Sign up to request clarification or add additional context in comments.

5 Comments

Just to clarify, to use this I should have something that checks that the index of item is not -1? sorry I am a bit confused on how this would work
@Nick, indexOf method returns some values, -1 means that an item not exists in one array.
ok, so item will be the id I am trying to remove, and if it is -1, I remove it? isn't it already removed to return -1?
oh ok, I also had to copy it. Ok, clear now. I'll give it a go, thanks
Thanks. It works perfectly fine. I had to spend a bit of time adjusting it, but it's working. Thank you very much
0

Simply putting,

Clone the original array in another variable (clonedArray) and compare the two after you are done deleting.

:)

Comments

0

Simplify the logic:

  • delete whatever you're going to delete
  • add the default values back in after each delete operation, e.g.:

    • for each default, check if it's already in the array and push if not
    • optionally sort the result if order matters to you

That's a simple, idempotent operation.


Alternatively, create a class that has the defaults as a property and the user-selected items as a separate property, and which merges both together conditionally as needed whenever necessary, e.g. basket.getMergedBasket().


Alternatively, instead of trying to maintain two lists, make those products objects if they aren't already which have an appropriate flag, e.g.:

products = [{ id: 1, mandatory: true }, ...]

That would be a really simple object oriented approach.

2 Comments

The problem is that I'd like to hide the minus button on the front end to prevent user from removing products that cannot be removed, that's why I would like a different approach than remove/add back in again
Then make those products objects if they aren't already and add a boolean deletable property to them.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.