代码之家  ›  专栏  ›  技术社区  ›  naspy971

关于使用Array.includes()和测试重复项的JavaScript问题

  •  3
  • naspy971  · 技术社区  · 7 年前

    我有一个输入,它使用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]])
    

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

    但我最终还是得到了重复项,我想这与数组的索引有关,它们是唯一的?也许是别的什么?

    Here's a result example

    4 回复  |  直到 7 年前
        1
  •  4
  •   nem035    7 年前

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

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

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

    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
  •  1
  •   JLRishe    7 年前

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

    例如,这会产生 false :

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

    因为 [1, 2]

    为了解决这个问题,您可以使用 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)
    }
    
        3
  •  1
  •   Carsten Massmann    7 年前

    另一种“老派”的做法可能是:声明一个对象( 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()
    
        4
  •  1
  •   Slaawwa    7 年前

    试试这个:

    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() (以及关于 find vs some 在jsPerf.com上):

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