Coleções

Uma coleção é um grupo (reunião, coletânea) de objetos que normalmente têm alguma relação entre si. Alguns exemplos de coleções são:

Dos exemplos acima podemos notar que  há diferentes tipos de coleções na vida real (sacos, caixas, estantes, filas, etc). Estas coleções diferem entre si pela forma como seus elementos estão organizados. Numa fila de supermercado, por exemplo, as pessoas ficam uma atrás das outras em função da ordem de chegada. Fato similar acontece com as músicas em um CD. Contudo, no caso do CD o número de músicas é fixo, enquanto que numa fila de supermercado o número de pessoas varia em função da velocidade com que elas são atendidas e em função da quantidade de gente que está dirigindo-se para um caixa. Uma boiada, por outro lado, não apresenta ordem nenhuma: os bois ficam completamente dispersos.

De forma similar ao descrito acima, Smalltalk oferece diferentes tipos de coleções (subclasses de Collection), a exemplo de:

As coleções em Smalltalk podem ser vistas como recipientes (depósitos) de objetos. Cada um dos diferentes tipos de coleções diferem dos outros pela forma como os elementos são armazenados, organizados e recuperados. Há, contudo, algumas ações que são comuns a todas as coleções. Há, também, várias tipos de iterações sobre coleções que se aplicam sobre todos os tipos. Estas operações são apresentadas no final deste texto.

 


Array

Um objeto do tipo Array é uma coleção de objetos que podem ser acessada por meio de um índice inteiro que representa a posição do elemento no Array.

Criando um Array x := Array new: 4.
Incluindo um objeto x at: 2 put: 'abc';
   at: 1 put: 23.45;
   at: 3 put: 456.
Recuperando um objeto y := x at: 2.
y := x first.
"O primeiro elemento do Array."
y := x last.
"O último elemento do Array."
Localizando um objeto y := x indexOf: 456.
"Índice do objeto 456 no Array"
y := x findFirst: [:obj | obj isString].
"Índice do primeiro objeto do Array que é um String"
y := x findLast: [:obj | obj isString].
"Índice do último objeto do Array que é um String"


String

Um String é uma seqüência de tamanho fixo de caracteres como letras, dígitos, sinais de pontuação e etc (código ASCII de 0 a 255). Um String pode ser visto como um caso particular de um Array no qual os elementos restringem-se a caracteres. Vale, portanto, tudo o que foi dito sobre objetos do tipo Array.

Criando um String x := String new: 4.
x at: 1 put: $T;
   at: 2 put: $u;
   at: 3 put: $d;
   at: 4 put: $o.
x := 'Tudo'.
Comparando Strings 'Oi' > 'Ai' [Image]
'Anterior' <= 'Posterior' [Image]
x  = 'Tudo' [Image]
x ~= 'tudo' [Image]
Alterando Strings y := 'Oi tudo bem'

y asArrayOfSubstrings.

[Image]

[Image]

y := '-123' asInteger. -123
y := 'Oi tudo bem?' asUpperCase. 'OI TUDO BEM?'
y := '      Oi tudo bem?   ' trimBlanks 'Oi tudo bem?'
y := 'Oi tudo bem?' upTo: $b. 'Oi tudo '
Concatenando Strings z := 'Tudo' , 'Bem'. 'TudoBem'
Copiando partes z := 'abcde efg' copyFrom: 3 to: 8 'cde ef'


OrderedCollection

Uma OrderedCollection pode ser visto como um Array dinâmico. Diferentemente das coleções de tamanho fixo (caso de Array e String), uma OrderedCollection pode crescer de forma a acomodar mais elementos. Seus elementos também podem ser removidos.  A ordem sugerida pelo nome desta coleção tem a haver com a ordem de inclusão dos elementos na coleção e não com a manutenção de algum critério de classificação de seus elementos (ver SortedCollection). São exemplos típicos de usos de OrderedCollection as  listas, filas e pilhas.


Set

Um conjunto (Set) representa uma coleção não ordenada de objetos. Seus elementos são únicos, ou seja, duplicações não são mantidas na coleção. Esta coleção guarda uma proximidade conceitual muito grande com a noção de conjuntos da matemática.


Ações comuns sobre coleções

convertendo asArray
asSet
asOrderedCollection
asSortedCollection
asString
"Retorna uma nova coleção organizada de maneira diferente, conforme o método"

Ex:
    #( 98 34 45 10 34 9 12 ) asSet ® Set(34 12 10 9 45 98 )

verificando conteúdo isEmpty "Retorna verdade (true) caso a coleção esteja vazia (não contenha nenhum elemento). Retorna falso (false) em caso contrário"
notEmpty "Retorna verdade (true) caso a coleção NÃO esteja vazia (contenha algum elemento). Retorna falso (false) em caso contrário"
size "Retorna o tamanho da coleção, ou seja, o número de elementos contidos nesta coleção"


Iterações sobre coleções

contando e localizando objetos occurrencesOf: umObjeto
"Retorna o número de elementos contidos na coleção que é igual a umObjeto"

Ex: contar quantas vezes o número 34 aparece na coleção:
    #( 98 34 45 10 34 9 12 ) occurrencesOf: 34 ® 2
includes: umObjeto
"Retorna verdade (true) se umObjeto está na coleção. Retorna falso (false) em caso contrário"

Ex: verificar se o número 45 está na coleção:
    #( 98 34 45 10 34 9 12 ) includes: 45 ® true
Ex: verificar se a cadeia de caracteres 'Joana' está na coleção:
    #( 'Maria' 'Pedro' 'João' ) includes: 'Joana' ® false
count: umBloco
"Avalia umBloco para cada elemento da coleção (tendo este elemento como argumento) e retorna o número de vezes que a avaliação resulta em valor verdade (true)."

Ex: contar quantos números da coleção são maiores que 30 e menores que 90:
    #( 98 34 45 10 38 9 12 ) count: [:numero | (numero > 30) & (numero < 90) ] ® 3
Ex: contar quantos vezes a letra "o" (maiúscula ou minúscula) aparece na coleção:
    'João Carlos de Oliveira' count: [:letra | letra asUpperCase = $O ] ® 4   
detect: umBloco
"Avalia umBloco para cada elemento da coleção (tendo este elemento como argumento) e retorna o primeiro elemento cuja avaliação resulta em valor verdade (true). É reportado um erro caso nenhum elemento resulte em valor verdade."

Ex: encontrar o primeiro número da coleção que seja maior que 35 e menor que 90:
    #( 98 34 45 10 38 9 12 ) detect: [:numero | (numero > 35) & (numero < 90) ] ® 45
Ex: encontrar o primeiro nome da coleção que comece com 'Pe':
    #( 'Maria' 'Pedro' 'João' ) detect: [:nome | nome beginsWith: 'Pe' ] ® 'Pedro'   

detect: umBloco ifNone: umBlocoDeFalha

"Avalia umBloco para cada elemento da coleção (tendo este elemento como argumento) e retorna o primeiro elemento cuja avaliação resulta em valor verdade (true). Caso nenhum elemento resulte em valor verdade, é retornado o resultado da avaliação de umBlocoDeFalha"

Ex:
    #( 98 34 95 10 28 ) detect: [:numero | (numero >= 35) & (numero < 90) ] ifNone:  [0] ® 0
    #( 'Maria' 'Pedro' 'João' ) detect: [:nome | nome beginsWith: 'Ab' ]
                           
ifNone:  ['Nenhum nome encontrado.'] ® 'Nennum nome encontrado'   
iterando sobre os elementos select: umBloco
"Avalia umBloco para cada elemento da coleção (tendo este elemento como argumento) e retorna uma nova coleção contendo apenas os elementos cuja avaliação resulta em valor verdade (true)."

Ex: selecionar os números da coleção que sejam maiores ou iguais a 35 e menores que 90:
    #( 98 34 45 10 38 9 12 ) select: [:numero | (numero >= 35) & (numero < 90) ]
                  
® #( 45 38 )
Ex: selecionar as letras do nome que não sejam o caracter branco ($ ):
    'João Carlos de Oliveira' select: [:caracter | caracter ~= $  ] ® 'JoãoCarlosdeOliveira'   
reject: umBloco
"Avalia umBloco para cada elemento da coleção (tendo este elemento como argumento) e retorna uma nova coleção contendo apenas os elementos cuja avaliação resulta em valor falso (false)."

Ex: rejeitar os números (selecionar os demais) da coleção que sejam maiores ou iguais a 35 e menores que 90 :
    #( 98 34 45 10 38 9 12 ) reject: [:numero | (numero >= 35) & (numero < 90) ]
                  
® #(98 34 10 9 12)
collect: umBloco
"Avalia umBloco para cada elemento da coleção (tendo este elemento como argumento) e retorna uma nova coleção contendo o resultado das avaliações."

Ex: obter o fatorial dos números:
    #( 5 7 2 4 ) collect: [:numero | numero factorial ] ® #(120 5040 2 24)

Ex: substituir as ocorrências do caracter $ã por $a:
    'João Carlos' collect: [:caracter | caracter = $ã ifTrue: [$a] ifFalse: [caracter] ]
                   
® 'Joao Carlos'   
do: umBloco
"Avalia umBloco para cada elemento da coleção (tendo este elemento como argumento)"

Ex: somar os número da coleção:
    |soma|
    soma := 0.
    #( 5 7 2 4 ) do: [:numero | soma := soma + numero] .

Ex: