Проблема с JavaScript при использовании Array.include () и тестировании дубликатов - PullRequest
0 голосов
/ 25 декабря 2018

У меня есть вход, который использует 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 получает тот же результат, поэтому я попытался это сделать:с индексами массива, которые являются уникальными?может быть что-то еще?

Here's a result example

Ответы [ 4 ]

0 голосов
/ 25 декабря 2018

Другой способ «старой школы» это сделать: объявить объект (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()
0 голосов
/ 25 декабря 2018

Array.prototype.includes выполняет проверку ссылочного равенства для объектов.

Это означает, что даже если вы нажимаете объекты одинаковой формы, они не являются одинаковыми ссылками, поскольку каждый запроссоздает новый объект.

Обычный шаблон - запоминать некоторую уникальную идентифицирующую часть объекта, например, идентификатор.

Может быть, вместо этого вы можете сохранить и проверить почтовый индекс?

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

Если вы решите использовать *Только 1016 *, тогда то, что вам нужно, можно также сделать, используя 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 выполняет сравнение на равенство для примитивных значений, таких как строки.

0 голосов
/ 25 декабря 2018

Array#includes не сравнивает ссылочные типы по их значениям;он сравнивает их, чтобы проверить, совпадают ли их ссылки.

Например, это производит false:

var myArr = [[5, 6], [1, 2], [4, 5]];

console.log(myArr.includes([1, 2]));  // false

, поскольку массив [1, 2] в строке 1 не совпадает с массивом в строке 3, даже если они содержат одинаковые значения.

Чтобы справиться с этим, вы можете вместо этого использовать Array#some, который принимает лямбда-функцию:

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)
}
0 голосов
/ 25 декабря 2018

Попробуйте это:

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