Colecciones: Arrays, Maps y Manipulación de Texto Unicode
Antes: Control de flujo y decisiones. Después: Funciones, ámbito y pipelines. Referencia técnica: Módulos nativos, Funciones globales.
¿Qué vas a aprender aquí?
Hasta ahora hemos trabajado con variables que almacenan un solo dato a la vez: un número, un nombre o un booleano. Pero en la vida real los datos casi nunca vienen aislados: - Una lista de productos en una tienda online. - Los comentarios de una publicación. - La ficha de un usuario con su nombre, correo, teléfono y dirección.
Para agrupar y organizar múltiples datos en una sola estructura, existen las colecciones.
En esta guía aprenderás paso a paso:
1. Qué es un array, cómo funciona la numeración desde cero (índices) y cómo añadir elementos.
2. Qué es un map (diccionario clave → valor) con llaves {} o estilo asociativo ["clave" => valor].
3. Cómo recorrer colecciones con foreach extrayendo tanto la posición o clave como el valor ($clave => $valor).
4. Cómo desempaquetar varios valores a la vez mediante desestructuración ([$a, $b] = ...).
5. Cómo funcionan las colecciones en la memoria (copia vs referencia compartida) y funciones útiles como count, merge, explode e implode.
6. Cómo maneja Joss el texto moderno Unicode (letras con tildes y emojis) y cómo convertir colecciones a JSON.
1. Arrays: Listas ordenadas de elementos
Un array es una lista ordenada de valores encerrados entre corchetes [ y ]. Cada valor ocupa una casilla numerada llamada índice.
En Joss (y en la mayoría de lenguajes de programación), los índices comienzan a contar desde cero (0), no desde uno:
- El primer elemento está en el índice 0.
- El segundo elemento está en el índice 1.
- El tercer elemento está en el índice 2.
var $compras = ["pan", "leche"]
print($compras[0])
$compras[] = "fruta"
print(count($compras))
print($compras[2])
Salida:
pan
3
fruta
Operaciones fundamentales con arrays:
- Creación: Se escriben entre corchetes
[y], separando los elementos con comas:["pan", "leche"]. Una lista vacía se escribe[]. - Lectura por índice:
$compras[0]obtiene el primer elemento ("pan"). - Modificar una posición:
$compras[1] = "queso"cambia el segundo elemento. - Añadir al final con
[]: Escribir$compras[] = "fruta"agrega el nuevo elemento al final de la lista automáticamente. - Contar elementos:
count($compras)(olen($compras)) devuelve cuántos elementos tiene la lista (3). - Protección de límites: Si intentas leer una casilla que no existe (como
$compras[99]o$compras[-1]), Joss detiene la operación de inmediato con el errorJOSS-INDEX-001(Index Out of Range), evitando lecturas de memoria inválidas.
Arrays con tipo fijo de elemento (array<Tipo>)
Por defecto, un array permite guardar distintos tipos de datos. Si quieres exigir que todos los elementos de una lista sean números enteros, puedes declararla con array<int>:
array<int> $edades = [18, 25, 30]
Expandir una lista dentro de otra con ... (Spread)
Puedes insertar todos los elementos de una lista existente dentro de una lista nueva anteponiendo tres puntos ...:
var $primeros = [2, 3]
var $todos = [1, ...$primeros, 4]
print($todos[0])
print($todos[1])
print($todos[2])
print($todos[3])
Salida:
1
2
3
4
2. Maps: Diccionarios de Clave → Valor
Un array es ideal cuando solo importa el orden (como una fila de turnos). Pero si quieres guardar la ficha de una persona con su nombre, edad y correo, recordar que “el nombre está en el 0 y la edad en el 1” es incómodo.
Para eso existen los maps (diccionarios o mapas asociativos). En un map, cada dato se guarda bajo una etiqueta de texto llamada clave:
var $persona = {"nombre": "Ada", "edad": 20}
print($persona["nombre"])
$persona["edad"] = 21
print($persona["edad"])
print($persona["telefono"] ?? "sin teléfono")
Salida:
Ada
21
sin teléfono
Características de los Maps en Joss:
- Creación con llaves
{}: Se asocia cada clave de texto con su valor usando dos puntos:{"nombre": "Ada", "edad": 20}. Un mapa vacío se escribe{}. - Lectura y modificación: Se escribe el nombre de la clave entre corchetes y comillas:
$persona["nombre"]. - Claves que no existen: Si consultas una clave que aún no ha sido guardada (como
$persona["telefono"]), Joss devuelvenullsin fallar. Combinarlo con??te permite mostrar un texto de respaldo limpio. - Verificar si una clave existe: La función integrada
array_key_exists("telefono", $persona)devuelvetrueofalse.
Notación alternativa con corchetes y flecha (=>)
Además de las llaves {}, Joss también acepta crear mapas usando corchetes [] y la flecha doble => (muy familiar si conoces PHP):
var $config = [
"app" => "JosSecurity",
"version" => "v1.0",
"autor" => ["nombre" => "Ada"]
]
print($config["app"])
print($config["version"])
print($config["autor"]["nombre"])
Salida:
JosSecurity
v1.0
Ada
Combinar mapas con ... (Spread)
Igual que en los arrays, puedes fusionar las claves de un mapa dentro de otro nuevo usando ...:
var $base = ["host" => "localhost", "puerto" => "8080"]
var $completo = [...$base, "seguro" => "true"]
print($completo["host"])
print($completo["puerto"])
print($completo["seguro"])
Salida:
localhost
8080
true
3. Recorrer Índices y Claves con foreach ($coleccion as $clave => $valor)
En el capítulo anterior vimos cómo recorrer los valores de una lista. Si también necesitas saber en qué posición o bajo qué clave está cada valor, escribe $clave => $valor dentro del foreach:
var $frutas = ["manzana", "pera"]
foreach ($frutas as $indice => $fruta) {
print($indice . ": " . $fruta)
}
var $letras = ["a" => "alfa", "b" => "beta"]
foreach ($letras as $k => $v) {
print($k . " => " . $v)
}
Salida:
0: manzana
1: pera
a => alfa
b => beta
Además, dispones de dos funciones directas para extraer las partes de un mapa:
- keys($mapa): Devuelve un array con todas las claves.
- values($mapa): Devuelve un array con todos los valores.
4. Desestructuración de Arrays y Maps
Cuando quieres extraer varios valores de un array o de un map y guardarlos en variables individuales en una sola línea, puedes usar la desestructuración, incluyendo valores por defecto por si algún dato falta:
[$x, $y, $z = 30] = [10, 20]
print($x)
print($y)
print($z)
{"nombre": $nombre, "rol": $rol = "cliente"} = {"nombre": "Ada"}
print($nombre)
print($rol)
Salida:
10
20
30
Ada
cliente
[!NOTE] Por compatibilidad, Joss también acepta la forma con paréntesis
let ($x, $y) = [10, 20], aunque la forma con corchetes[$x, $y] = [10, 20]es más expresiva y soporta valores por defecto.
5. Métodos directos sobre textos, listas y mapas (->)
En Joss, los textos (string), listas (array) y mapas (map) traen herramientas integradas (métodos) que puedes invocar escribiendo una flecha delgada -> después de la variable:
var $txt = " Hola Mundo "
print($txt->trim()->lower()->replace(" ", "-"))
var $mapa = {"a": 1, "b": 2}
print($mapa->keys()->join("-"))
Salida:
hola-mundo
a-b
Observa cómo se lee de izquierda a derecha:
1. $txt->trim(): Quita los espacios sobrantes de los extremos ("Hola Mundo").
2. ->lower(): Convierte las letras a minúsculas ("hola mundo").
3. ->replace(" ", "-"): Cambia el espacio por un guion ("hola-mundo").
Procesamiento funcional de listas
Joss también permite filtrar, transformar y sumar listas enteras con funciones como sum, filter, map, find, any y all (que exploraremos en profundidad en el próximo capítulo de Funciones):
var $numeros = [1, 2, 3, 4, 5]
var $pares = $numeros |> filter(func(int $x): bool { return $x % 2 == 0; })
var $escalados = $pares |> map(func(int $x): int { return $x * 10; })
print(sum($escalados))
var $encontrado = $numeros |> find(func(int $x): bool { return $x == 2; })
print($encontrado * 10)
print($numeros |> any(func(int $x): bool { return $x == 3; }))
var $txt = " Hola Mundo "
print($txt->trim()->lower()->replace(" ", "-"))
var $nums = [1, 2, 3, 4]
var $filtrados = $nums->map(func(int $n, int $i): int { return $n * 2; })->filter(func(int $n, int $i): bool { return $n > 4; })
print($filtrados->join(", "))
var $mapa = {"a": 1, "b": 2}
print($mapa->keys()->join("-"))
6. Comportamiento en memoria: ¿Copia independiente o lista compartida?
Hay una diferencia muy importante entre los datos simples y las colecciones:
- Cuando asignas un número o un texto a otra variable (
var $b = $a), se crea una copia independiente. - En cambio, cuando asignas un array o un map a otra variable (
var $copia = $original), ambas variables apuntan a la misma lista en la memoria:
var $original = [1, 2]
var $copia = $original
$copia[0] = 9
print($original[0])
var $datos = {"estado": "inicial"}
var $alias = $datos
$alias["estado"] = "nuevo"
print($datos["estado"])
Salida:
9
nuevo
Cambiar $copia[0] también cambió $original[0] porque ambas variables miran a la misma lista.
[!TIP] ¿Cómo crear una copia separada de un array? Si quieres duplicar una lista para modificar la nueva sin afectar la original, usa
merge:
var $clon = merge([], $original)
Funciones de extremos en listas (array_pop, array_shift, array_push)
Ten presente cómo funcionan estas tres funciones en Joss:
var $numeros = [1, 2]
print(array_pop($numeros))
print(count($numeros))
$numeros = array_push($numeros, 3)
print(count($numeros))
Salida:
2
2
3
array_pop($arr): Devuelve el último elemento sin borrarlo de la lista original.array_shift($arr): Devuelve el primer elemento sin borrarlo.array_push($arr, $item)(oappend($arr, $item)): Devuelve una nueva lista con el elemento añadido, por lo que puedes reasignarla ($numeros = array_push($numeros, 3)) o usar directamente$numeros[] = 3.
7. Texto Unicode: Letras visibles vs Bytes
En los idiomas modernos usamos tildes (á, é), eñes (ñ) y emojis (🚀). En la memoria de una computadora, un solo símbolo visible puede ocupar varios bytes.
Mira cómo Joss te permite medir exactamente lo que necesitas:
var $texto = "é"
print(len($texto))
print(strlen($texto))
print($texto[0])
Salida:
3
2
é
| Operación | Qué mide o devuelve | Cuándo usarla |
|---|---|---|
$texto[0] |
El carácter visible completo (grafema) | Cuando trabajas con nombres de personas o mensajes con tildes y emojis, sin romperlos por la mitad. |
strlen($texto) |
Cantidad de puntos de código Unicode | Para conteo estándar de caracteres Unicode. |
len($texto) |
Cantidad de bytes en memoria (UTF-8) | Para tamaños de archivo o envíos por red. |
8. Convertir colecciones a formato JSON (json_encode y json_decode)
JSON es el formato de texto universal para guardar datos en archivos o enviarlos por internet. Joss convierte cualquier array o map a JSON y viceversa con una sola instrucción:
Con mapas usando llaves {}:
var $perfil = {
"nombre": "Ada",
"lenguajes": ["Joss", "Go"]
}
var $jsonMapa = json_encode($perfil)
var $datosMapa = json_decode($jsonMapa)
print($datosMapa["nombre"])
print($datosMapa["lenguajes"][0])
Salida:
Ada
Joss
Con mapas usando corchetes [] y =>:
var $usuario = [
"nombre" => "Carlos",
"roles" => ["admin", "editor"]
]
var $jsonArray = json_encode($usuario)
var $datosArray = json_decode($jsonArray)
print($datosArray["nombre"])
print($datosArray["roles"][0])
Salida:
Carlos
admin
json_encode($datos): Convierte tu array o map en una cadena de texto JSON.json_decode($textoJson): Reconstruye el texto JSON en arrays y maps de Joss listos para usarse.json_verify($textoJson): Devuelvetruesi el texto es un JSON válido ofalsesi está mal formado.
9. Resumen de funciones esenciales para colecciones y texto
| Función | Propósito | Ejemplo | Resultado |
|---|---|---|---|
count($col) / len($col) |
Cantidad de elementos de un array o map | count([10, 20]) |
2 |
in_array($val, $arr) |
¿Existe el valor dentro del array? | in_array(2, [1, 2, 3]) |
true |
keys($map) |
Lista con todas las claves del map | keys({"a": 1}) |
["a"] |
values($map) |
Lista con todos los valores del map | values({"a": 1}) |
[1] |
explode($sep, $str) |
Parte un texto en un array usando un separador | explode(",", "a,b,c") |
["a", "b", "c"] |
implode($sep, $arr) |
Une un array de textos con un separador | implode("-", ["2026", "10", "17"]) |
"2026-10-17" |
array_reverse($arr) |
Invierte el orden de un array | array_reverse([1, 2, 3]) |
[3, 2, 1] |
10. Práctica del capítulo
1. Prueba rápida
En el ejemplo de la sección 1:
1. Agrega un cuarto producto a $compras escribiendo $compras[] = "café".
2. Muestra en pantalla el primer elemento ($compras[0]) y el total de productos con count($compras).
2. Ejercicio guiado: Ficha de inventario con un Map
- Crea en tu
main.jossun mapa llamado$productocon tres claves:"nombre": "Laptop","precio": 1200.00my"stock": 5. - Muestra sus datos:
print("Producto: " . $producto["nombre"] . " | Stock: " . $producto["stock"]). - Simula una venta restando
1a$producto["stock"]($producto["stock"] = $producto["stock"] - 1). - Convierte
$productoa JSON conprint(json_encode($producto)).
3. Reto: Gestor de lista de tareas
- Crea un array
var $tareas = ["Instalar Joss", "Crear proyecto"]. - Añade dos tareas más usando
$tareas[] = .... - Recorre la lista con
foreach ($tareas as $indice => $tarea)e imprime cada tarea numerada desde el1(pista: usa${$indice + 1}: ${tarea}).
Siguiente paso
Ahora que sabes representar listas, diccionarios y JSON en memoria, aprenderemos a organizar nuestro código en piezas reutilizables, limpias y con nombre propio: las funciones.
Continúa con: Funciones, ámbito de variables (scope), guard, defer, closures y pipelines.