仅当值不存在时才使用 lodash 推送到数组?

Posted

技术标签:

【中文标题】仅当值不存在时才使用 lodash 推送到数组?【英文标题】:Using lodash push to an array only if value doesn't exist? 【发布时间】:2016-09-01 14:37:35 【问题描述】:

我正在尝试创建一个数组,如果一个值不存在,则添加它,但是如果该值存在,我也想从数组中删除该值。

感觉 Lodash 应该可以做这样的事情。

我对您的最佳做法建议很感兴趣。

另外值得指出的是,我使用的是 Angular.js

* 更新 *

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

【问题讨论】:

示例输入和输出会有所帮助。加上你尝试过的。 在现代 javascript 环境中,使用 Set 比使用数组要好得多。 【参考方案1】:

你可以使用_.union

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

【讨论】:

太棒了,这太棒了。【参考方案2】:

ES6 引入的Set 特性正是这样做的。

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

或者如果您想继续使用常规数组

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

在 Lodash 上使用 vanilla JS 是一种很好的做法。它消除了依赖,迫使你理解你的代码,而且通常更高效。

【讨论】:

使用set支持什么? 看起来像 add() 函数中的代码是错误的:array.indexOf(value) !== -1,应该是 array.indexOf (值) === -1 代替。当前的代码逻辑是:如果项目已经存在 - 添加。 Lodash 与原生性能对比:github.com/you-dont-need/You-Dont-Know-Lodash-Underscore#_each “在 Lodash 上使用 vanilla JS 是一种很好的做法。” - 重新发明***绝不是好的做法,除非,在分析您的代码后确定有问题的代码是一个瓶颈。优化非瓶颈并不会提高您的应用程序的性能,实际上可能会产生负面的整体影响,因为优化非瓶颈所花费的每一分钟都是没有花在重要事情上的一分钟。一般来说,最好使用已经编写和调试过的代码(当 profiling 不指导您时)。 @floribon Lodash 允许我们创建更具可读性的代码并在挂钩下拥有出色的性能。无论您的功能是简单还是复杂,我确实看到了使用它的更多优势,它也带来了它的复杂性,但这是我自己的观点。至于使用 VanillaJS,我必须在这里说实话,在我看来,那样想是很糟糕的。为了夸大这一点,你也可以说使用 VanillaJS 而不是像 Angular/React 这样的框架很棒......现在,使用 TypeScript 和 Lodash 会更好,因为它比你通常使用的打字要好得多。【参考方案3】:

也许_.pull() 可以帮忙:

var _ = require('lodash');

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

改变现有数组,同时删除重复项:

> 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 ]

【讨论】:

【参考方案4】:

使用includes函数检查数组中是否存在项目,使用remove删除现有项目。

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>

【讨论】:

我喜欢这个答案,亚历克斯,但我试过了,它似乎对我不起作用。 似乎添加得很好,但如果再次触发该函数,则不会删除该值。我已经用代码 sn-p 更新了我的问题【参考方案5】:

在这种情况下,您可以使用“concat”推送并使用“uniq”验证唯一值:

示例:

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

例如:https://codepen.io/dieterich/pen/xeZNJY

参考:https://lodash.com/docs/4.17.11#uniq

【讨论】:

【参考方案6】:

这个单班轮应该可以完成这项工作。如果要插入的元素不存在,则插入该元素并返回结果数组的长度。如果元素存在于数组中,则删除该元素并在单独的数组中返回删除的元素。

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>");

实际上我讨厌 push,因为它返回的结果数组长度值在大多数情况下是无用的。我希望引用要返回的结果数组,以便您可以链接函数。因此,实现它的一种简单方法是;

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>");

所以现在这是合理的可链接的。

【讨论】:

【参考方案7】:

如果你不需要支持 IE,或者你正在使用 polyfills,你可以使用Array.prototype.includes()

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

【讨论】:

【参考方案8】:

最简单的方法是使用 _.isEmpty 和 _.remove Lodash 函数:

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

remove函数后会返回被删除的值或空数组,如果返回空数组则添加一个新值。

【讨论】:

以上是关于仅当值不存在时才使用 lodash 推送到数组?的主要内容,如果未能解决你的问题,请参考以下文章

仅当值不存在时才返回行

Spring - 仅当值不为空时才设置属性

sql Oracle:仅当值存在时才从另一个表中插入值

如果javascript中不存在值,如何推送到多维数组

如果特定键不存在,则将对象推送到数组[重复]

FluentValidation - 仅当值不为空时检查值是表达式