Deduplica un feed paginado por id

Empate

Requisito

Un feed de productos llega en tres páginas cuyos bordes se solapan, así que algunos artículos aparecen en dos páginas. Aplana las páginas e imprime cada artículo exactamente una vez — gana la primera aparición, se conserva el orden de llegada — con su id numérico como clave. Las páginas están en el código; las dos versiones deben imprimir las líneas que aparecen bajo Salida esperada.

Salida esperada
#101 Desk lamp
#102 Notebook
#103 Pen set
#104 Stapler
#105 Monitor arm
#106 Desk mat

Lado a lado

RxDart

FxDart

Por qué difieren

El dato interesante es dónde están los duplicados. Los bordes de las páginas se solapan, así que un id repetido llega en una página distinta — nunca junto a su primera aparición una vez aplanadas las páginas. Ese es exactamente el trabajo que el Stream.distinct corriente hace mal en silencio: es solo adyacente, así que en este feed dejaría pasar de largo todas las repeticiones. La deduplicación aquí necesita memoria de todo el feed, mientras que el aplanado en sí es fluido en ambos modelos — expand en el stream, flatMap en la cadena pull.

Como en la pareja de los visitantes únicos, la deduplicación global es distinctUnique contra uniqBy — una pareja equals/hashCode frente a una sola función de clave — y la división de nombres adyacente-contra-global es la que recorre la página de los cambios de estado. Ambos lados mantienen el mismo conjunto de claves vistas y preservan el orden de primera llegada, así que el veredicto es un empate — la versión pull simplemente se mantiene síncrona porque las páginas están en una lista local.

Benchmark

Apple M1 Max, 32 GB de RAM · Dart 3.12.2 (compilado AOT) · 2026-08-18

N = 100

Tiempo Empate

RxDart 25 µs
FxDart 12 µs

Memoria pico Empate

RxDart 16.5 MB
FxDart 16.5 MB

N = 1,000,000

Tiempo Gana FxDart

RxDart 319.5 ms
FxDart 204.1 ms

Memoria pico Gana FxDart

RxDart 302.1 MB
FxDart 241.0 MB

Las barras son medianas de iteraciones cronometradas repetidas en procesos nuevos por lado (los N pequeños se agrupan por resolución del temporizador). Dos lados a menos del 5% entre sí — o a menos de 0.6 ms, una diferencia que nadie puede percibir — cuentan como empate; las carreras relativas ajustadas se vuelven a medir hasta 5 veces. En una app, cualquier cosa por debajo de unos pocos milisegundos es invisible para el usuario, gane la barra que gane. La memoria es el RSS pico del proceso. La VM de Dart y el dataset son idénticos en ambos lados, así que la diferencia entre las dos barras es lo que retiene el pipeline en sí.