1
votes

Comment optimiser un 'pour' imbriqué dans la programmation fonctionnelle

J'ai créé une fonction pour vérifier s'il y a des numéros de téléphone portable répétés dans une liste. Le problème est que je l'ai fait en utilisant nested for. Comment pourrais-je optimiser ce code avec une programmation fonctionnelle?

  checkDuplicate(): boolean {

    for (let i = 0; i < this.phoneList.length; i++) {
      for (let j = 0; j < this.phoneList.length; j++) {
        if (i != j) {
            if (this.phoneList[i].number === this.phoneList[j].number) {
              this.toastrService.error('Phone already in List!');
              return true;
            }
        }
      }
    }

    return false;
  }


3 commentaires

checkout Array.filter ()


L'optimal dépendra également des données et du navigateur réels, car sur des navigateurs très anciens, un tandis que (this.phoneList.length--) sera plus rapide


Est-ce que cela répond à votre question? Supprimer les doublons d'un tableau d'objets dans JavaScript


6 Réponses :


1
votes

encore mieux que le filtre (que j'ai suggéré dans un commentaire), utilisez Set - il y a plusieurs façons de le faire mais c'est assez propre. Cependant .filter () serait probablement considéré comme plus 'fonctionnel' car il s'agit d'un HOC

let a = [1,2,1,3,3,5]
let x = [...new Set(a)]

// => [1, 2, 3, 5]

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set


1 commentaires

Propre en effet, mais il semble d'après le code de l'OP que chaque élément du tableau est un objet (d'où la référence à .number ), donc cela ne fonctionnera pas.



1
votes

Vous pouvez faire quelque chose comme:

let dups = this.phoneList.filter(item =>
    this.phoneList.filter(item2 => item.number == item2.number).length > 1
);
if (dups.length) {
    this.toastrService.error('Phone already in List!');
    return true;
}

... même si cela souffre un peu pour la lisibilité.


1 commentaires

" bien qu'il en souffre un peu pour la lisibilité. " et les performances, car c'est O (n ^ 2) identique à la solution d'OP.



2
votes

Solution O (n)

Ce n'est pas une fonctionnalité mais c'est la plus rapide à ce jour.

const checkDuplicate = (phones)=> {
    let counts = {};
    
    for(let phone of phones) {
        if(counts[phone.number]) return true;
        counts[phone.number] = 1;
    }

    return false;
}

if(checkDuplicate(this.phoneList)) {
  this.toastrService.error('Phone already in List!');
}


2 commentaires

Veuillez expliquer comment votre réponse compare this.phoneList.number pour les doublons


Cela échoue toujours, changez en let count = {}; pour utiliser correctement la propriété d'objet de cette façon



1
votes

Vous pouvez utiliser Array.some pour vérifier si un numéro de téléphone est un doublon, comme indiqué ci-dessous. Dans la boucle de rappel, le numéro de téléphone est la clé d'une valeur booléenne ajoutée à l'objet exist . La boucle s'arrête dès que la fonction de rappel renvoie true , ce qui se produit lorsqu'une clé / valeur correspondant à l'élément de la boucle est trouvée dans existe .

checkDuplicate(): boolean {
  let exists: { [key: number]: boolean } = {};
  return this.phoneList.some(phoneListItem => {
    if (exists[phoneListItem.number]) {
      return true;
    } else {
      exists[phoneListItem.number] = true;
      return false;
    }
  });
}


0 commentaires

4
votes

Vous pouvez créer un ensemble contenant uniquement les nombres uniques et comparer la longueur de l'ensemble à la longueur du tableau d'origine

hasDuplicates(): boolean {
  return new Set(this.phoneList.map(p => p.number)).size < this.phoneList.length
}


0 commentaires

1
votes

Ce n'est pas vraiment une question angulaire mais juste du JavaScript. Vous pouvez simplement faire un cycle court la boucle sur la liste comme plus rapide.

Chaque boucle interne est n-i plus rapide (moins à faire / vérifier) ​​puisque nous avons déjà vérifié ces

var xObj = {
  phoneList: [{
      name: "freddy",
      number: 55512121234
    }, {
      name: "Jimmy",
      number: 55512121234
    }, {
      name: "Mommy",
      number: 55512121233
    },
    {
      name: "Tommy",
      number: 55512121244
    },
    {
      name: "Luka",
      number: 55512121222
    },
    {
      name: "Penny",
      number: 55512121255
    },
    {
      name: "Sammy",
      number: 55512121266
    },
    {
      name: "Bill",
      number: 55512121244
    }
  ],
  phoneList2: [{
      name: "freddy",
      number: 55512121234
    }, {
      name: "Jimmy",
      number: 55512121235
    }, {
      name: "Mommy",
      number: 55512121233
    },
    {
      name: "Tommy",
      number: 55512121244
    },
    {
      name: "Luka",
      number: 55512121222
    },
    {
      name: "Penny",
      number: 55512121259
    },
    {
      name: "Sammy",
      number: 55512121266
    },
    {
      name: "Bill",
      number: 55512121247
    }
  ],
  toastrService: {
    error: function(message) {
      console.log(message);
    }
  },
  checkDuplicate: function() {
    let hasDupe = false
    for (let i = 0; i < this.phoneList.length; i++) {
      for (let j = i + 1; j < this.phoneList.length; j++) {
        if (this.phoneList[i].number === this.phoneList[j].number) {
          hasDupe = true;
          break;
        }
      }
      if (hasDupe) break;
    }
    if (hasDupe) this.toastrService.error('Phone already in List!');
    return hasDupe;
  },
  checkDuplicate2: function() {
    let hasDupe = false
    for (let i = 0; i < this.phoneList2.length; i++) {
      for (let j = i + 1; j < this.phoneList2.length; j++) {
        if (this.phoneList2[i].number === this.phoneList2[j].number) {
          hasDupe = true;
          break;
        }
      }
      if (hasDupe) break;
    }
    if (hasDupe) this.toastrService.error('Phone already in List!');
    return hasDupe;
  }
};
let cdup = xObj.checkDuplicate();
let cdup2 = xObj.checkDuplicate2();

console.log("dup:", cdup, cdup2);


3 commentaires

C'est encore O (n ^ 2) . Oui, c'est plus rapide que de parcourir tout le tableau, mais cela ne change pas la complexité temporelle.


Cela dépend également du tableau puisque si le premier et le deuxième correspondent ou si le deuxième et le troisième correspondent, cela se fait à ce point avec true. Cela fonctionne également sur les anciens navigateurs.


Les navigateurs plus anciens n'ont pas Set, mais vous pouvez toujours utiliser un objet simple et vous pouvez en utiliser un pour parcourir le tableau et suivre les valeurs. Vous obtenez toujours une récupération en temps constant et toute la complexité de l'algorithme est O (n) . En fait, avec un objet, vous aurez l'avantage d'avoir la même complexité du meilleur cas et une bien meilleure complexité moyenne et pire des cas.