tilbage til lektionen

Filtrer anagrammer

vigtighed: 4

Anagrams er ord der har det samme antal individuelle tegn men i en anden rækkefølge.

For eksempel:

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

Skriv en funktion aclean(arr) der returnerer et array renset for anagrammer.

For eksempel:

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

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

Fra hvert anagramgruppe skal der kun være ét ord tilbage, uanset hvilket.

Åbn en sandbox med tests.

For at finde alle anagrammer kan vi opdele hvert ord i bogstaver og sortere dem. Når bogstaverne er sorteret, er alle anagrammer ens.

For eksempel:

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

Vi bruger de bogstav-sorterede varianter som map-nøgler for kun at gemme én værdi per nøgle:

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

  for (let word of arr) {
    // opsplit ordet i bogstaver, sorter dem og sæt dem sammen igen
    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) );

Bogstav-sortering udføres af kæden af kald i linjen (*).

For nemheds skyld deler vi det op i flere linjer:

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

To forskellige ord 'PAN' og 'nap' får den samme bogstav-sorterede form 'anp'.

Næste linje sætter ordet ind i map’et med den bogstav-sorterede form som nøgle:

map.set(sorted, word);

Hvis vi nogensinde møder et ord med den samme bogstav-sorterede form igen, vil det overskrive den tidligere værdi med den samme nøgle i map’et. Så vi vil altid have højst ét ord per bogstav-form.

Til sidst tager Array.from(map.values()) en iterable over map-værdier (vi behøver ikke nøgler i resultatet) og returnerer et array af dem.

Her kunne vi også bruge et almindeligt objekt i stedet for Map, fordi nøglerne er strenge.

En løsning kan se sådan ud:

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

Åbn løsningen med tests i en sandbox.