Using lodash push to an array only if value doesn't exist?

JavascriptArraysAngularjsLodash

Javascript Problem Overview


I'm trying to make an array that if a value doesn't exist then it is added but however if the value is there I would like to remove that value from the array as well.

Feels like Lodash should be able to do something like this.

I'm interested in your best practises suggestions.

Also it is worth pointing out that I am using Angular.js

*** Update ***

if (!_.includes(scope.index, val)) {
    scope.index.push(val);
} else {
  _.remove(scope.index, val);
}

Javascript Solutions


Solution 1 - Javascript

You can use _.union

_.union(scope.index, [val]);

Solution 2 - Javascript

The Set feature introduced by ES6 would do exactly that.

var s = new Set();

// Adding alues
s.add('hello');
s.add('world');
s.add('hello'); // already exists

// Removing values
s.delete('world');

var array = Array.from(s);

Or if you want to keep using regular Arrays

function add(array, value) {
  if (array.indexOf(value) === -1) {
    array.push(value);
  }
}

function remove(array, value) {
  var index = array.indexOf(value);
  if (index !== -1) {
    array.splice(index, 1);
  }
}

Using vanilla JS over Lodash is a good practice. It removes a dependency, forces you to understand your code, and often is more performant.

Solution 3 - Javascript

Perhaps _.pull() can help:

var _ = require('lodash');

function knock(arr,val){ 
   if(arr.length === _.pull(arr,val).length){
      arr.push(val);
   } 
   return arr;
}

Mutates the existing array, removes duplicates as well:

> var arr = [1,2,3,4,4,5];

> knock(arr,4);
[ 1, 2, 3, 5 ]

> knock(arr,6);
[ 1, 2, 3, 5, 6 ]

> knock(arr,6);
[ 1, 2, 3, 5 ]

Solution 4 - Javascript

Use includes function to check that item is exists in array, and remove to delete existing item.

function addOrRemove(arr, val) {
  if (!_.includes(arr, val)) {
    arr.push(val);
  } else {
    _.remove(arr, item => item === val);
  }
  console.log(arr);
}

var arr = [1, 2, 3];
addOrRemove(arr, 1); // arr = [2, 3]
addOrRemove(arr, 4); // arr = [2, 3, 4]
addOrRemove(arr, 2); // arr = [3, 4]

<script src="https://raw.githubusercontent.com/lodash/lodash/4.11.2/dist/lodash.min.js"></script>

Solution 5 - Javascript

In this case you can use 'concat' to push and 'uniq' to validate unique values:

example:

var ar = [1, 2, 3, 1, 5, 2, 4]
ar = _.uniq(_.concat(ar, 9))
//[1, 2, 3, 5, 4, 9]

e.g.: https://codepen.io/dieterich/pen/xeZNJY

ref.: https://lodash.com/docs/4.17.11#uniq

Solution 6 - Javascript

This single liner should do the job. If element to be inserted does not exist, it inserts the element and returns the length of the resulting array. If element exists in the array it deletes the element and returns the deleted element in a separate array.

var arr = [1,2,3,4,5],
    aod = (a,e,i=0) => !!~(i = a.indexOf(e)) ? a.splice(i,1) : a.push(e); 
    
document.write("<pre>" + JSON.stringify(aod(arr,6)) + JSON.stringify(arr) + "</pre>");
document.write("<pre>" + JSON.stringify(aod(arr,6)) + JSON.stringify(arr) + "</pre>");

Well actually i hate push since it returns the resulting array length value which is most of the time useless. I would prefer to have a reference to the resulting array to be returned so that you can chain the functions. Accordingly a simple way to achieve it is;

var arr = [1,2,3,4,5],
    aod = (a,e,i=0) => !!~(i = a.indexOf(e)) ? a.splice(i,1) : (a.push(e),a);
        
document.write("<pre>" + JSON.stringify(aod(arr,6)) + JSON.stringify(arr) + "</pre>");
document.write("<pre>" + JSON.stringify(aod(arr,6)) + JSON.stringify(arr) + "</pre>");

So now this is reasonably chainable.

Solution 7 - Javascript

If you don't need to support IE, or if you are using polyfills, you can use Array.prototype.includes()

const addUniq = (array, value) => array.includes(value) 
  ? array.length 
  : array.push(value);

Solution 8 - Javascript

The simplest way to do this is use _.isEmpty and _.remove Lodash functions:

if (_.isEmpty(_.remove(array, value)) {
   array.push(value);
}

After remove function will be return removed values or an empty array, and if return an empty array then we will add a new value.

Solution 9 - Javascript

It's an old question but what you are looking for is XOR Lodash xor

It adds the value if is not already there and removes it otherwise. Great for toggle use-cases.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMax LynnView Question on Stackoverflow
Solution 1 - JavascriptAfzal HossainView Answer on Stackoverflow
Solution 2 - JavascriptfloribonView Answer on Stackoverflow
Solution 3 - JavascriptS.D.View Answer on Stackoverflow
Solution 4 - JavascriptalexmacView Answer on Stackoverflow
Solution 5 - JavascriptDarlan DieterichView Answer on Stackoverflow
Solution 6 - JavascriptReduView Answer on Stackoverflow
Solution 7 - JavascriptRich HowellView Answer on Stackoverflow
Solution 8 - JavascriptjedicodeView Answer on Stackoverflow
Solution 9 - JavascriptcifuentesView Answer on Stackoverflow