torna alle lezioni

Filtrare anagrammi

importanza: 4

Gli anagrammi sono parole che hanno le stesse lettere, ma in un ordine differente.

Ad esempio:

nap - pan
ear - are - era
cheaters - hectares - teachers

Scrivete una funzione aclean(arr) che ritorna un array ripulito dagli anagrammi.

Ad esempio:

let arr = ["nap", "teachers", "cheaters", "PAN", "ear", "era", "hectares"];

alert( aclean(arr) ); // "nap,teachers,ear" or "PAN,cheaters,era"

Da ogni gruppo di anagrammi dovrebbe rimanere solamente una parola, non ha importanza quale.

Apri una sandbox con i test.

Per trovare tutti gli anagrammi, dividiamo ogni parola in lettere ed ordiniamole. Con le lettere ordinate, tutti gli anagrammi sono uguali.

Ad esempio:

nap, pan -> anp
ear, era, are -> aer
cheaters, hectares, teachers -> aceehrst
...

Utilizzeremo la variante con le lettere ordinate come chiave di una map per memorizzare un solo valore:

function aclean(arr) {
  let map = new Map();

  for (let word of arr) {
    // dividi la parola in lettere, ordinale e ricongiungile
    let sorted = word.toLowerCase().split('').sort().join(''); // (*)
    map.set(sorted, word);
  }

  return Array.from(map.values());
}

let arr = ["nap", "teachers", "cheaters", "PAN", "ear", "era", "hectares"];

alert( aclean(arr) );

L’ordinamento delle lettere è fatto dalla concatenazione di chiamate alla riga (*).

Per convenzione le dividiamo in più linee:

let sorted = word // PAN
  .toLowerCase() // pan
  .split('') // ['p','a','n']
  .sort() // ['a','n','p']
  .join(''); // anp

Due parole diverse 'PAN' e 'nap' possiedono la stessa forma in lettere ordinate 'anp'.

La prossima lettera inserirà la parola nella map:

map.set(sorted, word);

Se abbiamo già incontrato una parola con la stessa forma, la sovrascriviamo con quella nuova, in modo tale da avere sempre una sola occorrenza all’interno della map.

Alla fine Array.from(map.values()) prende un iteratore sui valori di map (non abbiamo bisogno delle chiavi nel risultato) e ne ritorna un array.

Qui potremmo anche utilizzare un normale oggetto piuttosto di Map, poiché le chiavi sono stringhe.

Questo è un esempio di possibile soluzione:

function aclean(arr) {
  let obj = {};

  for (let i = 0; i < arr.length; i++) {
    let sorted = arr[i].toLowerCase().split("").sort().join("");
    obj[sorted] = arr[i];
  }

  return Object.values(obj);
}

let arr = ["nap", "teachers", "cheaters", "PAN", "ear", "era", "hectares"];

alert( aclean(arr) );

Apri la soluzione con i test in una sandbox.