Python y JavaScript lado a lado
La tabla de equivalencias que vas a consultar todo el curso, más las trampas donde el mismo algoritmo pasa en un lenguaje y falla en el otro.
8 min de lectura
Cada problema del curso se puede resolver en Python o en JavaScript. Esta lección es de consulta: vuelve cuando no recuerdes cómo se hace algo en el otro lenguaje.
Al final están las cuatro diferencias que producen bugs reales, no solo cambios de sintaxis. Esas conviene leerlas una vez completas.
Estructuras de datos
| Necesitas | Python | JavaScript |
|---|---|---|
| Array dinámico | lista = [] | const arr = [] |
| Largo | len(lista) | arr.length |
| Agregar al final | lista.append(x) | arr.push(x) |
| Sacar del final | lista.pop() | arr.pop() |
| Diccionario | d = {} | const m = new Map() |
| Conjunto | s = set() | const s = new Set() |
| Stack | una lista con append y pop | un array con push y pop |
| Cola | collections.deque | array con shift (lento) o dos punteros |
| Heap | heapq | no existe, se implementa |
| Tupla inmutable | (a, b) | [a, b] o Object.freeze |
Diccionarios
| Operación | Python | JavaScript |
|---|---|---|
| Crear | d = {} | const m = new Map() |
| Guardar | d[k] = v | m.set(k, v) |
| Leer | d[k] | m.get(k) |
| Leer con default | d.get(k, 0) | m.get(k) ?? 0 |
| ¿Existe? | k in d | m.has(k) |
| Borrar | del d[k] | m.delete(k) |
| Cantidad | len(d) | m.size |
| Recorrer | for k, v in d.items(): | for (const [k, v] of m) |
| Contar frecuencias | Counter(lista) | recorrer con set y get |
El patrón de contar, que aparece en decenas de problemas:
from collections import defaultdict
frecuencia = defaultdict(int)
for x in lista:
frecuencia[x] += 1
const frecuencia = new Map();
for (const x of lista) {
frecuencia.set(x, (frecuencia.get(x) ?? 0) + 1);
}
Usa Map y no un objeto {}. Un objeto convierte todas las claves a string, así que 1 y "1" colisionan, y además pierde el orden de inserción para claves numéricas. Map acepta cualquier tipo como clave y conserva el orden.
Conjuntos
| Operación | Python | JavaScript |
|---|---|---|
| Crear vacío | s = set() | const s = new Set() |
| Desde lista | set(lista) | new Set(lista) |
| Agregar | s.add(x) | s.add(x) |
| ¿Está? | x in s | s.has(x) |
| Quitar | s.discard(x) | s.delete(x) |
| Cantidad | len(s) | s.size |
| A lista | list(s) | [...s] |
Strings
| Operación | Python | JavaScript |
|---|---|---|
| Largo | len(s) | s.length |
| Carácter en i | s[i] | s[i] |
| Subcadena | s[i:j] | s.slice(i, j) |
| Últimos k | s[-k:] | s.slice(-k) |
| Invertir | s[::-1] | [...s].reverse().join("") |
| Separar | s.split(",") | s.split(",") |
| Unir | "".join(partes) | partes.join("") |
| A minúsculas | s.lower() | s.toLowerCase() |
| ¿Es letra o dígito? | c.isalnum() | /[a-z0-9]/i.test(c) |
| Carácter a número | ord(c) | c.charCodeAt(0) |
| Número a carácter | chr(n) | String.fromCharCode(n) |
| Posición en el alfabeto | ord(c) - ord('a') | c.charCodeAt(0) - 97 |
En los dos lenguajes los strings son inmutables, así que concatenar dentro de un loop es O(n²) en ambos. Acumula en una lista y une al final.
Ordenar
| Necesitas | Python | JavaScript |
|---|---|---|
| Copia ordenada | sorted(arr) | [...arr].sort((a,b) => a-b) |
| En el lugar | arr.sort() | arr.sort((a,b) => a-b) |
| Descendente | sorted(arr, reverse=True) | [...arr].sort((a,b) => b-a) |
| Por una clave | sorted(arr, key=lambda x: x[1]) | [...arr].sort((a,b) => a[1]-b[1]) |
| Dos criterios | key=lambda x: (x[1], x[0]) | (a,b) => (a[1]-b[1]) || (a[0]-b[0]) |
Loops y recorridos
| Necesitas | Python | JavaScript |
|---|---|---|
| De 0 a n-1 | for i in range(n): | for (let i = 0; i < n; i++) |
| Sobre los valores | for x in arr: | for (const x of arr) |
| Índice y valor | for i, x in enumerate(arr): | for (const [i, x] of arr.entries()) |
| Hacia atrás | for i in range(n-1, -1, -1): | for (let i = n-1; i >= 0; i--) |
| Dos listas a la vez | for a, b in zip(xs, ys): | xs.forEach((a, i) => ...) con ys[i] |
| Transformar | [f(x) for x in arr] | arr.map(f) |
| Filtrar | [x for x in arr if p(x)] | arr.filter(p) |
| Sumar todo | sum(arr) | arr.reduce((a,b) => a+b, 0) |
| Máximo | max(arr) | Math.max(...arr) |
Math.max(...arr) se rompe con arrays muy grandes porque el spread agota la pila de argumentos. Con más de unos 100.000 elementos, usa un loop o reduce.
Números
| Necesitas | Python | JavaScript |
|---|---|---|
| División entera | a // b | Math.floor(a / b) |
| División real | a / b | a / b |
| Potencia | a ** b | a ** b |
| Valor absoluto | abs(x) | Math.abs(x) |
| Infinito | float('inf') | Infinity |
| Menos infinito | float('-inf') | -Infinity |
| Entero más grande seguro | no hay límite | Number.MAX_SAFE_INTEGER |
Matrices
Crear una matriz de ceros de f filas por c columnas:
matriz = [[0] * c for _ in range(f)]
const matriz = Array.from({ length: f }, () => new Array(c).fill(0));
Las cuatro trampas que sí producen bugs
Lo anterior son diferencias de sintaxis: si te equivocas, el programa falla y lo ves. Estas cuatro son peores, porque el código corre y devuelve un resultado incorrecto.
1. El módulo con negativos
-3 % 5 # 2 en Python
-3 % 5 // -3 en JavaScript
Python siempre devuelve un resultado con el signo del divisor. JavaScript conserva el signo del dividendo. Cuando usas el módulo como clave de un diccionario, en JavaScript terminas con -3 y 2 como claves distintas cuando deberían ser la misma.
La normalización:
const resto = ((x % k) + k) % k;
Aparece en el problema de subarrays divisibles por K, y es la causa típica de que el mismo algoritmo pase en Python y falle en JavaScript.
2. La división entera con negativos
-7 // 2 # -4, redondea hacia abajo
Math.floor(-7 / 2) // -4, igual
Math.trunc(-7 / 2) // -3, corta hacia cero
Math.floor es el equivalente de //. Si usas Math.trunc o | 0, los negativos salen distintos. Aparece al calcular el punto medio en búsqueda binaria sobre rangos que pueden ser negativos.
3. Copias contra referencias
b = a # b es el mismo objeto que a
b = a[:] # copia superficial
b = [fila[:] for fila in a] # copia de una matriz
const b = a; // misma referencia
const b = [...a]; // copia superficial
const b = a.map(f => [...f]); // copia de una matriz
En backtracking esto muerde siempre: si agregas el camino actual al resultado sin copiarlo, todas las entradas del resultado apuntan al mismo array y terminan vacías cuando el algoritmo deshace sus pasos.
4. El heap no existe en JavaScript
Python trae heapq, que es un min-heap sobre una lista normal:
import heapq
h = []
heapq.heappush(h, 5)
heapq.heappush(h, 1)
menor = heapq.heappop(h) # 1
Para un max-heap, empuja los valores negados.
JavaScript no tiene nada equivalente en el lenguaje ni en la librería estándar. En una entrevista de JavaScript tienes tres salidas: implementarlo (está en la lección de heap de este curso), usar un array ordenado si las inserciones son pocas, o decir en voz alta "aquí usaría una cola de prioridad" y seguir. La tercera opción es aceptable en la mayoría de entrevistas si explicas la complejidad que tendría.
Cuál elegir
Para entrevistas, Python suele convenir: menos código, sin comparadores en el sort, heapq incluido, y enteros sin límite de tamaño.
JavaScript conviene si es tu lenguaje diario y vas a un puesto de frontend o de Node, porque la fluidez pesa más que la comodidad de la librería. Lo que no conviene es elegir un lenguaje que no dominas porque "es mejor para entrevistas". Perder tiempo con la sintaxis cuesta más que escribir un heap a mano.
Inicia sesión para guardar el progreso de esta lección.