Estruturas de Dados
Em algumas linguagens de programação, existem algumas estruturas de dados muito comuns, como Arrays. Já vimos os Arrays, porém Javascript também vem com Maps e Sets já inclusos.
Sets são como conjuntos na matemática: um conjunto de valores, porém sem repetição. Ou seja, em um Array normal, podemos ter elementos repetidos: [1, 2, 1, 2]. Porém em um Set, não teriamos essa repetição.
Outra diferença importante, é que Sets não usam indices para armazenar os valores, a gente simplesmente insere eles no conjunto, sem se preocupar com um índice.
Podemos criar um novo Set vazio fazendo let set = new Set();. Essa palavra new será aprofundada nos próximos capitulos (no capitulo 16 - Class).
Para inserir elementos no Set, podemos usar o método set.add(valor). Podemos por qualquer elemento em um Set: números, strings, até mesmo objetos ou outros Sets.
Exemplo:
let set = new Set();
set.add(1);
set.add(2);
set.add("frase");
Para verificar se já existe algum elemento no Set, podemos usar o método set.has(valor);
Exemplo:
let set = new Set();
set.add(1);
console.log(set.has(1)); // true
Também podemos remover um elemento de um Set, usando set.delete(valor).
Exemplo:
let set = new Set();
set.add(1);
console.log(set.has(1)); // true
set.delete(1);
console.log(set.has(1)); // false
Para iterarmos em cada elemento do Set, isto é, ler cada valor que está no Set, podemos usar o método set.forEach(funcao).
Esse método é similar ao método Array.forEach que estudamos em capitulos anteriores, ele recebe uma função que vai ser chamada pelo Javascript, e essa função recebe três parâmetros:
- O elemento atual que está sendo lido
- O elemento atual que está sendo lido (sim, existe essa redundância por motivos de compatibilidade, esses dois parâmetros terão os mesmos valores)
- O objeto Set que está sendo percorrido
Exemplo - imprimindo todos os elementos de um Set:
let set = new Set();
set.add(1);
set.add(2);
set.add("3");
set.add(2);
function imprimeElementos(valor, chave, set) {
console.log(valor);
}
set.forEach(imprimeElementos);
// 1
// 2
// "3"
Perceba no exemplo acima que embora adicionamos o valor 2 2 vezes, ele só aparece 1 vez, pois não temos elementos repetidos em um Set. Também perceba que o segundo argumento da função imprimeElementos se chama chave, dei esse nome para seguir a documentação da MDN, que explica melhor esse método.
E é assim que podemos utilizar Sets em Javascript. Outros métodos úteis para Sets podem ser encontrados diretamente na documentação da MDN.
Também existe uma estrutura de dados extremamente útil: Map.
Em linguagens como Java, usamos Maps para fazer um mapeamento chave-valor.
Ok, isso pode lembrar um pouco da sintaxe de objetos em Javascript, pois ela também realiza um mapeamento chave-valor.
Porém, existem algumas diferenças entre Maps e Objects no Javascript.
Usando objetos, nós só podemos ter identificadores comum de variáveis, ou no máximo strings como uma chave.
Exemplo:
let meuObjeto = {};
meuObjeto.chave1 = "bla";
meuObjeto["chaveDoidera"] = "hm";
meuObjeto["chave mais Louca ainda"] = "eita";
Usando strings, temos um pouco mais de flexibilidade para nossas chaves. Porém, usando a sintaxe de ., podemos ter erros se a nossa chave contém espaços, e também não podemos ter chaves como outros objetos por exemplo.
O código abaixo resulta em um erro.
let meuObjeto = {};
meuObjeto.chave com espaco = "bla";
Porém, com Map, podemos usar tanto valores primitivos quando objetos como chaves, e também temos alguns métodos extremamente úteis, que não possuimos se tivermos apenas um Object para fazer mapeamento chave-valor.
Para inicializar um Map vazio, podemos fazer let map = new Map();
Para adicionar um par chave-valor no mapa, devemos usar o método map.set(chave, valor).
Lembrando que as chaves e os valores podem ser de qualquer tipo, quando estivermos utilizando um Map.
let map = new Map();
map.set("chave1", "valor1");
let chaveObjeto = {nome: "chave maneira};
map.set(chaveObjeto, "uau");
Um detalhe muito importante sobre o método map.set: se uma chave já tiver sido inserida, e for inserida novamente, o valor anterior será sobrescrito.
Exemplo:
let map = new Map();
map.set("chave1", "valor1");
map.set("chave1", "uau");
// agora o valor ligado a chave "chave1" é a string "uau"
Para obter o valor ligado a uma chave, usamos map.get(chave).
Exemplo:
console.log(map.get("chave1")); // "valor1"
console.log(map.get(chaveObjeto)); // "uau"
É possível verificar se existe uma determinada chave em um mapa, usando o método map.has.
Exemplo:
let map = new Map();
map.set("chave", "valor");
console.log(map.has("chave")); // true
console.log(map.has("chaveDiferente")); // false
Também é possível verificar quantos elementos foram inseridos em um Map, utilizando a propriedade map.size.
Exemplo:
let myMap = new Map();
myMap.set("a", "alpha");
myMap.set("b", "beta");
myMap.set("g", "gamma");
console.log(myMap.size); // 3
Por fim, também temos o método map.forEach(funcao), que atua de forma similar ao método set.forEach(funcao).
Esse método espera receber como parâmetro uma função com 3 parâmetros:
- O valor do elemento atual que está sendo lido
- A respectiva chave do elemento atual que está sendo lido
- O objeto Map que está sendo percorrido
Vamos a um exemplo: mostrando todos os pares chave-valor que estão inseridos em um Map.
let myMap = new Map();
myMap.set("a", "alpha");
myMap.set("b", "beta");
myMap.set("g", "gamma");
function mostraChaveValor(valor, chave, objetoMap) {
console.log(chave + " - " + valor);
}
myMap.forEach(mostraChaveValor);
Execute essa função e veja o resultado :)
Bem, temos essas duas estruturas de dados em Javascript, elas são úteis em algumas situações, então é útil conhecer elas.
Tenha cautela na diferença entre Map e um Object comum. Map é bem mais flexível no quesito das chaves, e também vem com uma série de métodos utilitários, que auxiliam no mapeamento e operações envolvendo chave-valor, portanto, utilize com sabedoria :)