{"id":232456,"date":"2023-01-13T20:34:00","date_gmt":"2023-01-13T17:34:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=232456"},"modified":"2022-11-10T09:40:33","modified_gmt":"2022-11-10T06:40:33","slug":"come-creare-una-mappa-bidirezionale-in-javascript","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/it\/come-creare-una-mappa-bidirezionale-in-javascript\/","title":{"rendered":"Come creare una mappa bidirezionale in JavaScript"},"content":{"rendered":"\n<p>Una mappa bidirezionale \u00e8 un modello dell&#8217;informatica in cui le coppie chiave-valore hanno una relazione biunivoca 1-1 tra le chiavi e i valori. Questo ci consente non solo di interrogare per chiave e ottenere un valore, ma anche di interrogare per valore e ottenere la chiave. Vediamo come implementare una mappa bidirezionale in JavaScript e in seguito rendiamola sicura in TypeScript<\/p>\n<h2>L&#8217;informatica e la matematica dietro<\/h2>\n<p>Prendiamo una definizione di base di una mappa bidirezionale:<\/p>\n<blockquote>\n<p>In informatica, una <strong>mappa bidirezionale<\/strong> \u00e8 una struttura di dati associativa in cui le coppie chiave-valore formano una corrispondenza uno-a-uno. Quindi la relazione binaria \u00e8 funzionale in ogni direzione: ogni valore pu\u00f2 anche essere mappato su una chiave univoca.<\/p>\n<\/blockquote>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-157501-61e6b9e14822e.png\" data-rel=\"lightbox\" ><img decoding=\"async\" class=\"SDStudio-light-box-enable SDStudio-editor-tools-md-imp\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-157501-61e6b9e14822e.png\" alt=\"Come creare una mappa bidirezionale in JavaScript\" ><\/a><\/p>\n<p>Credito: <a href=\"https:\/\/en.wikipedia.org\/wiki\/Bidirectional_map\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">mappa bidirezionale<\/a><\/p>\n<p>La mappa bidirezionale dell&#8217;informatica ha le sue radici in una funzione matematica chiamata biiezione. La relazione tra i componenti di una coppia con ciascuno dei suoi componenti in insiemi diversi \u00e8 una funzione biiettiva, detta anche funzione invertibile, che \u00e8 una funzione che funziona in entrambi i modi, accoppiando esattamente un elemento di un insieme con esattamente un elemento di l&#8217;altro set:<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-157501-61e6b9e2a629e.png\" data-rel=\"lightbox\"><img decoding=\"async\" class=\"SDStudio-light-box-enable SDStudio-editor-tools-md-imp\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-157501-61e6b9e2a629e.png\" alt=\"Come creare una mappa bidirezionale in JavaScript\" ><\/a><\/p>\n<p>Credito: <a href=\"https:\/\/en.wikipedia.org\/wiki\/Bijection\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Biiezione<\/a><\/p>\n<p>Con questo in mente possiamo sapere che una funzione biiettiva per gli insiemi sopra produrr\u00e0 qualcosa come:<\/p>\n<p>f (1) = D<br \/>\nf (C) = 3<\/p>\n<p>Un&#8217;altra cosa che deriva dalla funzione biiettiva \u00e8 che gli insiemi avranno esattamente la stessa lunghezza, altrimenti la biiezione fallirebbe.<\/p>\n<h2>Inizializzare la mappa bidirezionale<\/h2>\n<p>Lo modelleremo con una classe <a href=\"https:\/\/startfunction.com\/category\/javascript\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">JavaScript<\/a> che verr\u00e0 inizializzata con un oggetto di coppie chiave \u2013 valore:<\/p>\n<pre><code>const bimap = new BidirectionalMap({\n  a: 'A',\n  b: 'B',\n  c: 'C',\n})<\/code><\/pre>\n<p>Internamente creeremo due liste. Una lista memorizzer\u00e0 l&#8217;elenco di coppie di quella che chiameremo una mappa diretta, dove le mappe chiave da valutare e sar\u00e0 una copia dell&#8217;oggetto che abbiamo usato per inizializzare la mappa bidirezionale. Il secondo elenco sar\u00e0 quella che chiameremo mappa inversa e memorizzer\u00e0 una versione dell&#8217;oggetto utilizzato per inizializzare la mappa bidirezionale in cui le coppie chiave-valore sono state capovolte e il &quot;valore&quot; ora viene mappato sulla &quot;chiave&quot;:<\/p>\n<pre><code>class BidirectionalMap {\n  fwdMap = {}\n  revMap = {}\n\n  constructor(map) {\n      this.fwdMap = { ...map }\n      this.revMap = Object.keys(map).reduce(\n          (acc, cur) =&gt; ({\n              ...acc,\n              [map[cur]]: cur,\n          }),\n          {}) }\n}<\/code><\/pre>\n<p>Nota che a causa della natura dell&#8217;oggetto che inizializza la mappa bidirezionale non puoi usare un numero per la chiave ma puoi comunque usarlo come valore e sarai in seguito in grado di interrogarlo:<\/p>\n<pre><code>const bimap = new BidirectionalMap({\n  a: 42,\n  b: 'B',\n  c: 'C',\n})<\/code><\/pre>\n<p>Una versione pi\u00f9 robusta sebbene anche pi\u00f9 complessa potrebbe essere scritta con il <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Map\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">tipo di dati Map<\/a> di JavaScript e consentire chiavi che sono numeri, funzioni o persino NaN.<\/p>\n<h2>Ottieni un elemento da una mappa bidirezionale<\/h2>\n<p>Fino a questo punto, abbiamo una struttura dati che ospita due oggetti, uno dei quali \u00e8 lo specchio dell&#8217;altro in termini di valori chiave. Ora abbiamo bisogno di un metodo per ottenere qualcosa da esso. Implementiamo una <code>get()<\/code>funzione:<\/p>\n<pre><code>  get( key) {\n      return this.fwdMap[key] || this.revMap[key]\n  }<\/code><\/pre>\n<p>\u00c8 molto semplice: se esiste nella mappa in avanti, lo restituiamo, altrimenti lo restituiamo dalla mappa invertita. Se non esiste, <code>undefined<\/code>verr\u00e0 restituito.<\/p>\n<p>Ora possiamo ottenere alcuni elementi come:<\/p>\n<pre><code>console.log( bimap.get('a')) console.log( bimap.get('A')) <\/code><\/pre>\n<h2>Aggiungi un elemento a una mappa bidirezionale<\/h2>\n<p>La nostra mappa al momento non ha un modo per aggiungere pi\u00f9 elementi, quindi aggiungiamo una funzione per aggiungere nuovi elementi alla mappa:<\/p>\n<pre><code>  add( pair) {\n    this.fwdMap[pair[0]] = pair[1]\n    this.revMap[pair[1]] = pair[0]\n  }<\/code><\/pre>\n<p>Questo ricever\u00e0 una matrice di due elementi, che in seguito digiteremo come una tupla con <a href=\"https:\/\/startfunction.com\/tag\/typescript\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">TypeScript<\/a> e li assegner\u00e0 come valori chiave in entrambe le direzioni agli oggetti corrispondenti.<\/p>\n<p>E ora possiamo aggiungere una coppia e interrogare questa nuova coppia<\/p>\n<pre><code>bimap.add(['d', 'D'])\nconsole.log( bimap.get('D')) <\/code><\/pre>\n<h2>Una mappa bidirezionale sicura per i tipi in TypeScript<\/h2>\n<p>Per migliorare le cose e digitare in modo sicuro possiamo riscriverlo in TypeScript e aggiungere concetti di digitazione come un oggetto generico durante l&#8217;inizializzazione della mappa e una <a href=\"https:\/\/www.typescriptlang.org\/docs\/handbook\/basic-types.html#tuple\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">tupla<\/a> quando si aggiunge un nuovo elemento.<\/p>\n<pre><code>class BidirectionalMap {\n  fwdMap = {}\n  revMap = {}\n\n  constructor(map: { [key: string]: string }) {\n      this.fwdMap = { ...map }\n      this.revMap = Object.keys(map).reduce(\n          (acc, cur) =&gt; ({\n              ...acc,\n              [map[cur]]: cur,\n          }),\n          {}) }\n\n  get(key: string): string | undefined {\n      return this.fwdMap[key] || this.revMap[key]\n  }\n\n  add(pair: [string, string]) {\n    this.fwdMap[pair[0]] = pair[1]\n    this.revMap[pair[1]] = pair[0]\n  }\n}<\/code><\/pre>\n<p>Questa digitazione ora rende la nostra mappa perfettamente sicura e garantisce, in questo caso, di utilizzare sempre le stringhe sia per le chiavi che per i valori.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Fonte di registrazione:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/startfunction.com\" class=\"external external_icon\">startfunction.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Puoi interrogare queste mappe per chiave e ottenere il suo valore o per valore e ottenere la sua chiave<\/p>\n","protected":false},"author":1,"featured_media":224548,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[896,731,751,720,844],"tags":[1168],"class_list":["post-232456","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-codice","category-javascript-6","category-open-source-projektmanagement-3","category-sviluppatore","category-tutorial","tag-affiai-it"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/posts\/232456","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/comments?post=232456"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/posts\/232456\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/media\/224548"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/media?parent=232456"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/categories?post=232456"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/tags?post=232456"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}