【问题标题】:Add items to an array skipping duplicates将项目添加到跳过重复项的数组
【发布时间】:2016-11-10 09:48:56
【问题描述】:

我想将项目添加到跳过重复项的数组中。但是由于某种原因,只添加了一项,而没有添加第二项。这是我的代码。

var add = ['email1@gmail.com', 'email2@gmail.com', 'email1@gmail.com'];
var main_messages = []
var from 
function findMessages(messageList) {
  return messageList = from;
}

add.map(function(map){
  from = map
  if(main_messages.find(findMessages) === undefined){
    main_messages.push(map)
  }
});

console.log(main_messages)

所以预期的输出应该是

['email1@gmail.com', 'email2@gmail.com']

但我在这段代码中得到的输出只是

['email1@gmail.com']

我做错了什么,我该如何解决这个问题?

【问题讨论】:

  • 只是一个提示,map 为每个元素返回一个返回值。如果未设置,则为undefined。你可能会寻找过滤器,如果返回一个真实值,它会返回项目。

标签: javascript


【解决方案1】:

看起来您在findMessages 的返回语句中缺少=,因此您基本上是将from 设置为messageList,而不是进行比较。这是固定代码

var add = ['email1@gmail.com', 'email2@gmail.com', 'email1@gmail.com'];
var main_messages = []
var from 
function findMessages(messageList) {
  return messageList === from;
}

add.map(function(map){
  from = map
  if(main_messages.find(findMessages) === undefined){
    main_messages.push(map)
  }
});

console.log(main_messages)

【讨论】:

  • 更好的是,使用===。
  • @QuentinRoy 是的
【解决方案2】:

考虑按以下方式使用数组的 JavaScript 1.6 / ECMAScript 5 原生 filter 方法:

var add = ['email1@gmail.com', 'email2@gmail.com', 'email1@gmail.com'];
var main_messages = add.filter(function(v, i, a) {return a.indexOf(v) === i;});

另一个应该提供更好性能 O(x) 的解决方案是使用 array.reduce:

main_messages = Object.keys(add.reduce(function (p,c) {return (p[c] = true,p);},{}));

两种解决方案都会产生包含以下内容的消息:

["email1@gmail.com", "email2@gmail.com"]

如果您需要支持没有实现此功能的浏览器,Mozilla 提供的 pollyfill 一如既往地提供(见页面底部)

【讨论】:

  • 注意filter((v, i, a) => ...可以写成filter(function(v,i,a){ ... } ,这样代码可以在所有浏览器中工作
  • @Alex 感谢您注意到这一点,已改为使用标准“功能”。
  • @QuentinRoy 添加了一个提供 O(n) 的 array.reduce 示例。感谢您指出这一点。
【解决方案3】:

我认为您在以下代码中的错误

function findMessages(messageList) {
  return messageList = from;
}

在这里,我认为您 return 对其父级,因此它显示了一个 vale。 为此,您需要将 messageList = from 存储在 var 中,然后返回该变量。

var x = messageList;
return x;

【讨论】:

    【解决方案4】:

    您可以实现uniq 函数。这是filter 的特殊形式。

    var add = ['email1@gmail.com', 'email2@gmail.com', 'email1@gmail.com'];
    var main_messages = uniq(add);
                                   
    function uniq(arr) {
    	var result = [];
    	for (var i = 0; i < arr.length; i++) {
    		if (result.indexOf(arr[i]) === -1) {
    			result.push(arr[i]);
    		}
    	}
    	return result;
    }
    
    console.log(main_messages)

    另一方面,map 将始终返回一个大小为 same 的数组,除非您当然不喜欢分配等。

    map 将数组的每个元素传递给一个回调函数,您可以使用该回调函数修改单个元素,而无需触及实际的数组。

    将其视为 1 进 1 出,依此类推,但您有机会更改数组中的 什么,而不是其中的 多少 .这个想法是,从 map 产生的数组与输入数组的长度相同,但内容不同。

    可以产生不同大小的数组的方法有filter和reduce。

    因此,您也可以这样做:

    var add = ['email1@gmail.com', 'email2@gmail.com', 'email1@gmail.com'];
    var main_messages = add.filter( (el, idx, input) => input.indexOf(el) === idx );
    console.log(main_messages)

    【讨论】:

      【解决方案5】:

      您可以使用indexOf 函数来检查重复项。您可以尝试以下方式将项目添加到您的数组中而不会重复。

      var add = ['email1@gmail.com', 'email2@gmail.com', 'email1@gmail.com'];
      var main_messages = []
      
      add.map(function(map){
        if(main_messages.indexOf(map) == -1){
          main_messages.push(map)
        }
      });
      console.log(main_messages);
      

      【讨论】:

        【解决方案6】:

        这是一个简单的答案:https://stackoverflow.com/a/18328062/5228251

        为什么要这么辛苦,使用专门针对此类操作的javascript filter函数可以更轻松地完成:

        var add = ['email1@gmail.com', 'email2@gmail.com', 'email1@gmail.com'];
        var main_messages = []
        
        main_messages = add.filter( function( item, index, inputArray ) {
                   return inputArray.indexOf(item) == index;
            });
        
        ------------------------
        Output: ['email1@gmail.com', 'email2@gmail.com']
        

        【讨论】:

          【解决方案7】:

          根据您的需要,使用 Set 代替数组可能是您想要的:

          Set 对象允许您存储任何类型的唯一值,无论是 原始值或对象引用。

          var add = ['email1@gmail.com', 'email1@gmail.com', 'email2@gmail.com', 'email1@gmail.com'];
          
          // Init from an iterable.
          var main_messages = new Set(add);
          
          // Add a new email (not previously in the set).
          main_messages.add('email3@gmail.com');
          
          // Try to add an existing email, does nothing.
          main_messages.add('email1@gmail.com');
          
          console.log('main_messages:')
          main_messages.forEach(msg => console.log('-', msg));

          当然,只有将数据保存在Set 中时,此选项才可行。每次插入后将其转换为数组会非常低效。

          Set 是一个 ES2015 特性。您可能需要检查compatibility table 并在需要时考虑使用polyfill。

          【讨论】:

            猜你喜欢
            • 2022-11-29
            • 2020-08-21
            • 2013-03-24
            • 1970-01-01
            • 2011-08-12
            • 1970-01-01
            • 2018-02-20
            • 2018-10-16
            • 1970-01-01
            相关资源
            最近更新 更多