【问题标题】:JavaScript issue on using Array.includes() and test duplicate items使用 Array.includes() 和测试重复项的 JavaScript 问题
【发布时间】:2019-05-24 05:39:19
【问题描述】:

我有一个输入,它使用 API 根据插入的字母来获取一些城市。 API 在每个 keyup 事件上启动,如下所示:

let ville_input = document.getElementById("search_immobilier_ville");
let ville_arr = [];

ville_input.addEventListener("keyup", () => {
  res_list.innerHTML = "";

  fetch("https://api.fr/communes?nom=" + ville_input.value)
    .then(res => {
      return res.json();
    })
    .then(data => {
      data.forEach(el => {
        if (
          el.codeDepartement == "971" &&
          el.nom
            .toUpperCase()
            .startsWith(ville_input.value.toUpperCase().trim())
        ) {
          if (!ville_arr.includes([el.nom, el.codesPostaux[0]])) {
            ville_arr.push([el.nom, el.codesPostaux[0]]);
            console.log(ville_arr);
          }
        }
      });
    })
    .catch(err => {
      // Doing stuff
    });
});

首先,我想将每个结果作为数组推送到一个数组中,如下所示:

ville_arr.push([el.nom,el.codesPostaux[0]])

我的问题是,当 API 获取相同的结果时,我将重复的项目放入我的数组中,这就是我尝试这样做的原因:

if(!ville_arr.includes([el.nom,el.codesPostaux[0]])){

    ville_arr.push([el.nom,el.codesPostaux[0]])
    console.log(ville_arr)

      }

但我最后还是得到了重复的项目,我想这与数组的索引是唯一的有关吗?也许还有别的?

【问题讨论】:

    标签: javascript arrays ajax fetch


    【解决方案1】:

    Array.prototype.includes 对对象进行引用相等检查。

    这意味着,即使您推送相同形状的对象,它们也不是相同的引用,因为每个请求都会创建一个新对象。

    通常的模式是记住对象的某些唯一标识部分,例如 id。

    也许您可以存储并检查邮政编码?

    if (!zipcodes.includes(el.codesPostaux[0])) {
      zipcodes.push(el.codesPostaux[0]);
      ville_arr.push([el.nom, el.codesPostaux[0]]);
    }
    

    一种省时的方法是使用一组邮政编码而不是一个数组(因为设置查找时间是 O(1)):

    if (!zipcodesSet.has(el.codesPostaux[0])) {
      zipcodesSet.add(el.codesPostaux[0]);
      ville_arr.push([el.nom, el.codesPostaux[0]]);
    }
    

    如果您决定只使用ville_arr,那么您也可以使用Array.prototype.every(或Array.prototype.some)来完成您需要的操作:

    // this will return true if every place in ville_arr
    // does not have the zipcode from the response
    if (ville_arr.every(([, zipcode]) => zipcode !== el.codesPostaux[0])) {
      ville_arr.push([el.nom, el.codesPostaux[0]]);
    }
    

    您还可以通过您的对象调用JSON.stringify 以从某个对象创建相同的字符串并保存可以使用的字符串,因为includes 对字符串等原始值进行相等比较。

    【讨论】:

      【解决方案2】:

      试试这个:

      const ville_input = document.getElementById('search_immobilier_ville');
      let ville_arr = [];
      ville_input.addEventListener('keyup', () => {
          res_list.innerHTML = '';
      
          fetch(`https://api.fr/communes?nom=${ville_input.value}`)
              .then(res => {
      
                  // Clear old data if get new response
                  ville_arr = [];
      
                  return res.json();
              })
              .then(...)
              .catch(...);
      });
      

      或尝试使用 Array.prototype.find()(以及 jsPerf.com 上有关 find vs some 的额外信息):

      if(!ville_arr.find(i => i[1] === el.codesPostaux[0])) {
      
          ville_arr.push([el.nom, el.codesPostaux[0]]);
          console.log(ville_arr);
      }
      

      【讨论】:

        【解决方案3】:

        Array#includes 不比较引用类型的值;它比较它们以检查它们的引用是否相同。

        例如,这会产生false:

        var myArr = [[5, 6], [1, 2], [4, 5]];
        
        console.log(myArr.includes([1, 2]));  // false

        因为第 1 行的 [1, 2] 数组与第 3 行的数组不同,即使它们包含相同的值。

        要解决这个问题,您可以改用Array#some,它接受一个 lambda 函数:

        var myArr = [[5, 6], [1, 2], [4, 5]];
        
        console.log(myArr.some(e => e[0] === 1 && e[1] === 2));  // true

        或者根据您的具体示例来说明:

        if(!ville_arr.some(e => e[0] === el.nom && e[1] === el.codesPostaux[0])) {
            ville_arr.push([el.nom,el.codesPostaux[0]])
            console.log(ville_arr)
        }
        

        【讨论】:

          【解决方案4】:

          另一种“老派”的做法可能是:声明一个对象 (o) 并使用从每个数组的内容生成的键向其中添加子数组。然后,该对象将自行保持其独特的结构:

          var o={d:{},add:function(nom,code){this.d[nom+code]=[nom,code]},
          get:function(){return Object.values(this.d)}};
          

          你添加值给它

          o.add(el.nom, el.codePosteaux[0]);
          

          并从中检索唯一数组

          o.get()
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2013-01-07
            • 2014-10-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多