Uma estrutura de dados fundamental que é subutilizada, mas altamente útil, é o tipo de conjunto. Felizmente, ele existe em muitos idiomas de uma forma ou de outra. Em C #, você tem o HashSet <T> genérico, em Objective-C você tem os objetos NSMutableSet e NSSet, e em Python você simplesmente tem o tipo de conjunto integrado além do conjunto congelado menos conhecido.
Não importa como sejam nomeados, como sejam construídos, todos são modelados a partir de uma construção matemática muito importante que é conhecida como o Conjunto. A definição de um conjunto é simplesmente uma coleção bem definida de objetos distintos. Os objetos que compõem o conjunto são conhecidos como membros desse conjunto. E, teoricamente, os conjuntos podem conter qualquer coisa: números, nomes, animais, planetas, gravatas-borboleta, outros conjuntos e assim por diante … você entendeu.
Normalmente, quando você está armazenando itens em um conjunto, geralmente é útil armazenar itens semelhantes ou semelhantes, mas não é obrigatório. Tudo depende do contexto do seu aplicativo e de como você interpreta esses dados. Vamos considerar algumas propriedades importantes da implementação de conjuntos bem projetados:
- Eles só possuem membros distintos
- Eles podem dizer o tamanho deles, também conhecido como cardinalidade
- Eles devem facilmente permitir que você teste se um membro já está presente no conjunto rapidamente
- Seus membros são armazenados em uma ordem indefinida
- Eles podem ser combinados de várias maneiras, produzindo novos conjuntos como resultado
Agora, antes de entrarmos nos detalhes, vamos falar rapidamente sobre os conjuntos em Go. Bem, para ser franco, não há conjuntos em Go. Eu realmente não tenho ideia de por que não há conjuntos em Go, visto que é um tipo de coleção muito fundamental que deveria estar em TODOS os idiomas na minha opinião mais humilde. Infelizmente, ele não está lá, pelo menos pelo que eu posso dizer e tem havido algumas perguntas nos fóruns de Go e grupos de e-mail sobre sua omissão.
Digite o conjunto de golang feito em casa: http://deckarep.github.io/golang-set/
Instruções de instalação:
go get github.com/deckarep/golang-set
Obtenha enquanto está quente! Vamos falar sobre como esse cachorrinho funciona:
//The 2013 winter schedule for freshmen and freshwomen.
requiredClasses := NewSet()
requiredClasses.Add("Cooking")
requiredClasses.Add("English")
requiredClasses.Add("Math")
requiredClasses.Add("Biology")
scienceClasses := NewSet()
scienceClasses.Add("Biology")
scienceClasses.Add("Chemistry")
electiveClasses := NewSet()
electiveClasses.Add("Welding")
electiveClasses.Add("Music")
electiveClasses.Add("Automotive")
bonusClasses := NewSet()
bonusClasses.Add("Go Programming")
bonusClasses.Add("Python Programming")
Suponha que estejamos tentando descobrir quais aulas assistir no primeiro ano do ensino médio. Olhamos o folheto da escola e imediatamente vemos que existem algumas aulas obrigatórias (gemido), algumas disciplinas eletivas para escolher e até mesmo, se quisermos obter alguns créditos extras para este ano, algumas aulas bônus.
Nada se estilhaçando até agora. Onde estamos, criamos quatro conjuntos distintos que contêm strings Go como membros desses conjuntos. Vamos ver que tipo de perguntas podemos responder e afirmações que podemos fazer sobre esses 4 conjuntos distintos.
Preciso dar ao meu amigo que está doente em casa uma lista de todas as aulas disponíveis. Vamos conseguir a união de todas essas classes e mandar para ele.
allClasses := requiredClasses.Union(scienceClasses).Union(electiveClasses).Union(bonusClasses)
Ótimo, agora eu tenho um novo conjunto chamado allClasses que posso enviar para ele. Este novo conjunto agora contém uma lista distinta de toda a programação de inverno, o que significa que Biologia não aparecerá no conjunto allClasses duas vezes, sim, por design.
Eu me pergunto agora se cozinhar é considerado uma aula de ciências hoje em dia, já que certos programas de culinária como Good Eats contêm muita ciência.
fmt.Println(scienceClasses.Contains("Cooking"))
//Returns: false
Deixa pra lá, que tal todas as aulas que eu posso assistir que não são aulas de ciências?
fmt.Println(allClasses.Difference(scienceClasses))
//Returns: Set{Music, Automotive, Go Programming, Python Programming, Cooking, English, Math, Welding}
Ok, interessante, que tal: quais das aulas de ciências também são aulas obrigatórias?
fmt.Println(scienceClasses.Intersect(requiredClasses))
//Returns: Set{Biology}
Quantas aulas de bônus são oferecidas para esta programação de inverno?
fmt.Println(bonusClasses.Cardinality())
//Returns: 2
Você tem alguma das seguintes aulas? Eu realmente gosto deles!
fmt.Println(allClasses.ContainsAll("Welding", "Automotive", "English"))
//Returns: true
Como você pode ver, podemos realmente responder a algumas perguntas pegando alguns conjuntos e compondo-os, decompondo-os e, geralmente, manipulando-os para responder a uma variedade de perguntas. E de forma alguma isso pretende ser uma referência exaustiva da manipulação de conjuntos, mas observe uma coisa. Sem loops! Este é o poder dos conjuntos, o poder de tratar também uma coleção de objetos, um Conjunto. Como exercício, como você teria realizado a mesma coisa usando outras coleções mais típicas, como uma fatia Go? Ou mesmo um mapa?
Espero que tenha sido divertido para você assim como foi para mim!
-Ralph
Se você gosta disso, considere meu outro artigo onde uso Go para construir um filtro simples de palavrões junto com conjuntos de Redis