Accede a todos mis cursos aquí y obtén un 10% de descuento para siempre en la suscripción con el cupón 'off10": academia.holamundo.io/bundles/acceso-a-todo
hola estimado, justo ayer en streaming te estaba dando las gracias, ya que para una tarea de base de datos donde no sabia nada de TypeScript y gracias a tu video "Aprende TypeScript ahora! curso intensivo" me salve con un 75 de 100, un abrazo desde viña del mar, Chile.
@@pedroorteganunez4158 acá mismo en el canal de TH-cam, activa las notificaciones y te saldrá, además TH-cam ahora cuenta con un apartado de en vivo o directos, donde puedes ver los directos pasados
Como adicional, esto se puede analizar facil pensandolo de esta forma, usando el reduce, estamos iterando 1 vez los usuarios (para crear el reduce) y 1 vez la otra lista que queremos marcar con el created_by_user. En cambio si usamos el find, estamos iterando potencialmente todos los usuarios en cada iteración de los elementos que queremos marcar. Es como pasar de tener 2 for uno abajo del otro, a dos for anidados. O sea, a grandes rasgos, el tiempo de ejecución pasa de 2*n a n^2. Esto quiere decir que la alternativa del find es exponencialmente mas lenta
Eso es lo malo de estos videos. No usan ciclos primitivos (2 for's y chan chan), y tiran de cosas que tambien son iteraciones, pero más rebuscadas (find, reduce, map, etc). No digo que esté mal usarlas, pero las explicaciones "primitivas" son importantes para transmitir el problema y su solución.
@@crayder03pienso igual y es por eso que al menos se debe tocar c o c++ leyendo un libro de análisis de algoritmos, bueno así lo aprendí en la universidad
Lo que comentas como primitivo es programación imperativa, las formas de iterar que mencionas entre paréntesis usan el paradigma de programación funcional que bajo a ciertos criterios se puede considerar mucho mejor que el imperativo, búscate las ventajas de la programación funcional @@crayder03
@@crayder03 Pues en mi caso me parece un reto lo que explica el video, no lo comprendí de primeras, pero estuve analizando el porqué y cómo funcionaba y luego comprendí. No considero que eso sea algo malo, uno ya se acostumbra que las explicaciones a veces no vienen con todo fácil y es trabajo de uno el analizarlo todo y así se aprende más.
no tanto porq al utilizar (find, reduce, map, etc) ya estaríamos con programación funcional y eso saca los for prácticamente, ya lo que si deberían leer como funcionan estas y cuando debemos utilizarlos @@crayder03
Podrías compartir cuanto tiempo te toma incluyendo el proceso de indexado con el reduce, para tener un panorama más cercano a solo usar find. Un saludo!
aqui es un problema de estructura de datos , es muy comun actualmente de usar arrays para todo , pero si vas a tener que realizar busquedas o multiples accesos es mejor usar Map u object dado que el acceso es de O(1) , en contra al O(n) esa es la idea , asi que cuando creas la structura de datos debes de pensar en eso y usar o un array o una estructura indexada ese es el problema , tmb puedes usar arboles ,binarios, monticulos , arboles balanceados , listas doble enlazadas ...dependiendo del tamaño y lo deseado multiples escrituras o lecturas o simplemente iteracion array ....
1. No es necesario hacer reduce. Puedes usar Map. 2. Funciona solo en casos de particiones heterógenas, donde cada valor es único. 3. El reduce debió haber sido agregado al benchmark. 4. Esta solución duplica el uso de memoria en largos datasets. 5. Usa un argumento función (thunk), exactamente lo mismo se puede hacer en un "for" simple. V8 tiene optimizaciones para for simples. 6. La solución no acepta case insensitve.
Como es reemplazable el reduce por un map? map regresa una lista y lo que el esta formando es un objeto de {[id]: usuario} supongo que podria hacer que el map haga pares de key:object y luego wrappearlo en Object.fromEntries, pero no hay mucha diferencia en "readability" o performance no?
Solo un apunte: al usar un objeto para crear el diccionario de usuarios, limitamos los tipos que podemos usar como clave (ya que todo se convierte a string). Una alternativa es usar el tipo Map, que tiene precisamente la finalidad de indexar objetos en base a una clave, y es más flexible que un objeto plano 🙂.
Ya hacia falta los videos de este estilo al canal, se extrañan los de indole personal y de motivación. Son tu trademark!. P.D. recuerdo cuando hiciste este video cuando recien llegaste a nueva zelanda. Sin los efectos, ni background como ahora. Era simple pero muy orgánico y con una pieza de información reutil.
Si el indexado por id coincide con el índice del array original, no hace falta crear otro objeto cuyas llaves son la id, ya que la array original misma sirve para la búsqueda.
@@csnzlatino En este caso el punto no es medir el reduce ya que se asume que este ya esta construido para ser usado multiples veces, por eso el ejemplo hace enfoque en el algoritmo de search que se supone va a ser utilizado en varias ocasiones
Por eso es común normalizar la data cuando viene de backend, normalizer por ejemplo puede transformar los array en hashTables y eso te salva la vida al momento de interactuar con la data.
@@letthesuntalk cambiaré nunca por muy excepcionalmente. Es muy poco probable que el front necesite tanta información. Si vas a montar una tabla, solo necesitas tener los elementos que quepan en pantalla. Si renderizas en un navegador una tabla con cientos de filas el rendimiento va a ser malo, no digamos ya miles. Si es un gráfico, los datos deben llegar ya agregados, no vas a mostrar un gráfico de columnas con 100 columnas en un eje. En definitiva, el front no debería procesar datos, idealmente deben llegar ya procesados y se limitará a mostrarlos. Indexar un array tiene sentido en el backend, pero en el front es más usable un array de, como máximo, unas decenas de datos ya procesados
@@elektropunkk9835 aún así estas enviando más información de la necesaria. El payload de la petición puede ser muy grande. No digo que no se pueda hacer, pero en la mayor parte de los casos es mejor que el front tenga lo justo y necesario
hola siento que soy un fracasado y pensé y no servía para nada pero me empezó a gustar la programación gracias a ti explicas de una manera comprensible, entendible pero la verdad aun no elijo a que lenguaje debería entrar pero gracias por hacer ala gente le guste la programación
usa javascript para aprender lo basico, los fundamentos, luego ver por un lenguaje orientado a objeto fuertemente tipado como JAVA. de ahi en adelante cualquier otro lenguaje sera pan comido, asi que profundiza estructura de datos y ejercicios de algoritmos, luego construye una web que haga algo valioso... no las tonteras de poke api. Saludos
Hola, pues llevo como desarrollandor junior 2 meses, creo que es verdad lo que comentan arriba, sigo sintiéndome fracasado y que no valgo aun cuando ya logro superar un problema difícil, lo que me ha ayudado es darme cuenta de que no soy el único, que es mejor aprender un poco cada día y seguir adelante, cuando menos lo esperes ya estarás muy avanzado en tu camino! Solo sigue adelante!
A todos nos pasa en algún momento eso de sentirnos fracasados, la cosa está en seguir aunque nos cueste, porque así tmb cuando nos sentimos inútiles, tmb nos sentimos increíbles cuando logramos aprender o superar algo q nos costó
Hay más variables a tener en cuenta, como en donde vive el índice, el tamaño del array de acuerdo a esto, cuál de los dos arrays a comprar crecerá más, uso mucho esta técnica pero hay que profundizar un poco más al usarla. Buen video.
Esta muy bueno este video. Para la proxima deberias incluir el tiempo que tarda el indexado, asi se tendria una apreciacion mas justa de cuanto tarda en total toda la operacion....
@@juan7114 Un ciclo dentro de otro ciclo tiene una escala exponencial, porque la cantidad de iteraciones de los ciclos se multiplica Un ciclo despues de otro (sin anidarse) tiene una escala lineal, porque las iteraciones se suman. Esto los hace mucho mas eficientes Busca videos de notacion Big O
*Batallita del dev:* Una vez hice un programa que trackeaba salas del primer resident evil y cada sala tenía una serie de coordenadas para pintar en el mapa la posición del jugador. Cada segundo realizaba 60 ops de posicionamiento, pero en vez de crear una bound function o un mapa, hice un listado de if else, en la práctica funciona muy bien, pero realmente a veces me dan ganas de volver atrás y optimizar ese código.
Con el .find estás realizando bucles anidados por lo que el tiempo es O(n^2) en cambio con el .reduce baja a O(n) de ahí la mejora, pero ojo que a cambio la memoria aumenta O(n)
ahí la memoria aumentaría por el mapa que se esta creando de los usuarios? igual pensaba en eso, guardar en memoría un array de 10mil o más igual me parece arriesgado, yo le dejaría la pega de filtrar e indexar a la base de datos.
Y crear el indexado tampoco es gratis, lleva su tiempo y habrá que "recrearlo" o insertar en el lugar adecuado si se modifica, que tambien lleva su tiempo. Todo depende del caso particular a resolver.
YO lo veo viable para hacerlo en el servidor que no se haga en el front, porque hacerlo en el front, conlleva memoria por el cliente. Y en otro caso, creería que es más viable de inmediato filtrarlo desde la base de datos, así evitas traerse tanta data y traerla de una vez purgada.
También pensé lo mismo. Al final lo probé en el código, igualmente es mucho mas rápido agregando el reduce dentro del console.time. Yo hice la prueba con 2000 iteraciones; con el método find demora 33ms y con el reduce 7 ms.
Hola, Hola Mundo! 😃 Para tomar el tiempo real de la segunda opción con los usuarios indexados, no sería necesario mover el console.time encima del reduce? Ya que este es necesario para poder aplicar el userIndexado. Saludos
Es cierto, pero de todos modos va a ser mucho menos porque con el indexado, tenemos 1 loop que itera todos los usuarios para hacer el reduce, y otro loop que itera todos los elementos que queremos marcar con el created_by_user. O sea 2*n. En cambio usando el find, estamos haciendo una iteración de los usuarios por cada elemento que queremos marcar, o sea n iteraciones de n usuarios, n^2
Totalmente de acuerdo @@Titere05 , no digo que esté mal la opción, al contrario, es genial. Simplemente que tampoco estamos mostrando el tiempo como debe ser, ya que deberia agregarse el tiempo para generar el indexado. Saludos!
igual el indexado también cuesta un tiempo el cuál no se está contando, en un caso así donde puedes preindexar todos los usuarios no hay mucho problema pero en algo que tenga usuarios dinámicos no puedes hacer un único indexado
el caso sería exactamente el mismo, ya que la actualización del diccionario de usuarios se hace en tiempos de ejecución distintos al de la búsqueda en cuestión. La función de búsqueda irá a consultar el espacio en memoria que otra función mutó en un tiempo de ejecución distinto al de la función de búsqueda. Es decir, en el momento en el que, por ejemplo, creas o eliminas usuarios, vas a actualizar la base de datos de usuarios e inmediatamente vas a modificar el indice para cuando alguien quiera consultarlo en otro momento.
Buen video, pero una observación. Esta implementación se vuelve ineficiente cuando tienes millones de usuarios para indexar (en términos de memoria), ya que cada usuario representa un hash que apunta a un lugar en la memoria y gestionarlos todos esos tiende a consumir mucha memoria muy rápido. Aunque en términos de búsqueda es muy eficiente computacionalmente (O(1)), para lograr una implementación eficiente tanto en memoria como en búsqueda, puedes utilizar un algoritmo simple de búsqueda binaria (manteniendo un array ordenado de elementos). Tener un array ordenado y buscar elementos representaría una complejidad de O(log(n)) en términos de cómputo al buscar elementos, pero consumiría solo O(n) en memoria. El único sacrificio sería que, en lugar de tener una complejidad de inserción de O(1), tendrías una complejidad de inserción de O(n) y aunque la búsqueda sería de O(log(n)) en lugar de O(1), esta complejidad es robusta y eficiente para prácticamente cualquier número industrial de usuarios u objetos. Edit: Las complejidades arriba son para acceder e insertar un solo elemento del índice.
También otra observación es que esta técnica es muy ineficiente cuando se tienen más procesos de escritura (como modificar o agregar) que de lectura dentro de estos objetos
@@leonel1387 La página de Wikipedia de búsqueda binaria discute su complejidad en mas detalle. Lo mismo para la página de tabla de hash (se discute más a detalle en la página en inglés que en la que está en español)
Que buen nivel en algunos comentarios, siempre que veo vídeos así, los comentarios solo son aduladores o trollers, pero aquí hay nivel en tus seguidores, que bien, creo eso debe ser más satisfactorio...
Es que esta mostrando un ejemplo básico (y pensado para que sea fácil de comprender), se asume que en la vida real no es así y que en vez de aplicar transformaciones con un map usaría un generador justamente para evitar el problema de la ram que mencionas.
Muy buen video y consejos, pero una salvedad: No mides el tiempo que tarda en crear el hashmap, diccionario o array asociativo. Eso tiene un coste tanto en memoria como tiempo (sí, es lineal, pero cuesta). La estrategia es ordenar la lista si vas a hacer varias consultas (de hecho, lo ideal es una inserción por orden), de este modo convertimos la búsqueda en log(n). El usar un índice es una estrategia similar a los índices de las bases de datos, pero tiene sus costes. El planteamiento es que los registros posean una estructura adecuada de inicio, el hecho de que sean random (que no es mal ejemplo para ilustrar lo que propones) nos hace saltar ese paso. Primero las estructuras adecuadas, luego los algoritmos.
cada problema está asociado a una estructura de datos: iteración: lists, arrays búsqueda: maps, trees recursión: stacks, trees desecho secuencial: queues un map por ejemplo es demasiado rápido, pero consume mucha memoria, así que no es una opción para hardware o entornos con recursos muy limitados... en cambio un árbol es un poco más lento (pero más rápido que una lista), y consume sólo la memoria que necesita, así que se hace más interesante en esos dispositivos.
En general, se asume que el precio de una buena tarjeta de memoria RAM es inferior al precio de un procesador, por ende, los desarrolladores prefieren sacrificar memoria que la sobre iteración de los procesos y ciclos, aunque en estos vídeos, uno queda con la falsa idea de que lo que se busca es la optimización en los tiempos de ejecución, cuando a un consumidor estandar ese dato le vale madres, para los proyectos que no sean de ciertos nichos inoficiosos.
Además, que en el vídeo tampoco se menciona nada sobre que es la manera en la cual se está ocupando la información en la RAM, y el modus operandi de la maquinaria en su arquitectura, lo que termina desarrollando mas o menos el mismo proceso que se está haciendo dentro del código con el uso de ciclos, pero de una manera más eficiente a cambio de consumir otro tipo de recursos de la máquina, al desarrollar operaciones matemáticas para obtener la ubicación de la información entre los espacios de la RAM, que en efecto, se van a encontrar considerablemente desperdiciados por la cantidad de posiciones en la ram que se encontrarán ocupadas y desperdiciadas al usar indexaciones que no sean numéricas y consecutivas.
@@1iamigo En JS, como en todos los lenguages con GC, usar memoria no solo es ocupar espacio de memoria sino que también hay que considerar el impacto en el procesamiento. Si no se tiene cuidado, los ciclos de GC pueden meter en algunos casos latencias esporádicas de varias decenas de ms y picos de usos de los procesadores. En un sistema productivo, la acumulación de estos ciclos se puede volver un problema mucho más grande del que muchos piensan. Es de hecho una de las causas más comunes de problemas de optimizacion.
@@javierolazaran7227 Así es, pero reitero, en el vídeo creo que se quedaron corto con respecto a estos temas, tampoco mencionaron nada sobre el orden de las funciones O(n)=n2 > 2n, etc... Simplemente dicen, "no uses esto, hazlo así porque si, y porque así dio "resultado"." Con esta manía, vamos a terminar con programadores que dicen ser pragmáticos, que solo van por resultados, pero que solo serán tan precoces como los mismos jefes, y serán igual de engreídos, vacíos y sin fundamentos.
No dudo en que sea mucho mas rapido pero creo que tambien debio incluir el tiempo de crear el objeto de users indexado, de igual forma creo que es tremenda entrategia para mejorar el performance.
En el trabajo a veces se presentan ocaciones donde se requiere buscar un usuario no solo por su id, sino por otro atributo. Pars eso se usaría un "composite key" sería genial tener un tutorial de eso. Saludos!
Gracias! Estava com problema de busca de dados em uma tabela que tem milhões de dados e, para essa consulta, tenho que recorrer em todas as linha afim de buscar o registro do usuário em específico.
Probe el código porque me dio curiosidad cuanto tiempo agregaba el Reduce para crear el usersIndexado y no afecto el resultado, es muy eficiente 👏. También me sirvió para ver la diferencia de potencia entre mi PC y la de Nicolas jajaja a el le tarda 0.4ms y a mi 4ms 😅😅
Yo uso precisamente la indexación para la importación masiva en formato csv, que puede tener miles de registros; con eso, hasta un computador lento lo hace parecer todo una supercomputadora
Yo hago esto mismo pero instanciando un Map: const usersMap = new Map() Luego lo relleno: users.forEach(user => usersMap.set(user.id, user)) Y para buscar un usuario: const user = usersMap.get(id) La del reducer la sabía, pero me pareció que lo natural era hacer un Map list, así que siempre me incliné por esta forma. Ahora bien, debería probar ambos casos a ver cuál performa mejor.
Habiendo hecho la tarea, pude comprobar que el método del reduce para indexar los datos es aproximadamente 2.5 veces más rápido que el de utilizar un Map list. Hice la prueba con 10 millones de usuarios y creando la lista con 10 millones de elementos. Con el reduce tarda mas o menos 3.77 segundos vs 9.37 segundos del Map.
Nico saludos desde ECUADOR cachai soy ecuatoriano bromeo seria bueno un curso de tu auditoria sobre php8 y mysql un crud en MVC Y USANDO OOP y saludos y que tal es estar en nueva zelanda
Interesante, mejora la performance. Pero justo al final del video me vino una pregunta, ¿Cuánto demora en hacer el indexado? Sumando el indexado al mapeo 0.445ms es menor a los 233.35ms? Gracias y un saludo Nico, siempre viendo tus videos cuando tengo tiempo
lo ideal es hacer lo que haces una entity en redux con ngrx tener un diccionario donde la clave es el id y el valor el objeto y tener tambien un array con los ids para cuando es util el orden o devolver todos los elementos como un array.
Ok, pero entonces cuando dura el proceso de indexado? Porque deberías de calcular el tiempo que toma indexar + el tiempo que toma la búsqueda, y bueno, manejar la posibilidad de que el índice no exista, pero eso también pasa con el método find
Completamente despreciable en comparacion a hacer la busqueda. Es comparar algo con O(N) contra (N**2). El indexado es mas costoso que una simple iteracion, pero sigue siendo una operacion O(N). Cuanto mas grande N, mas despreciable el valor (Comparar N**2 sobre N) la diferencia se hace mas grande cuanto mas grande N. Ejemplificado, para 1 millon de usuarios, el indexado costara una millonesima de lo que cuesta la busqueda con doble for, multiplicado por alguna constante, es decir, un numero muy pequeño
Accede a todos mis cursos aquí y obtén un 10% de descuento para siempre en la suscripción con el cupón 'off10": academia.holamundo.io/bundles/acceso-a-todo
Estos son los videos que me hicieron ver entero este canal, espero que estos video no se vuelvan a perder maestro Nico!!! :D
hola estimado, justo ayer en streaming te estaba dando las gracias, ya que para una tarea de base de datos donde no sabia nada de TypeScript y gracias a tu video "Aprende TypeScript ahora! curso intensivo" me salve con un 75 de 100, un abrazo desde viña del mar, Chile.
Hola podría saber donde hace Streaming HolaMundo?
Gracias!!
@@pedroorteganunez4158 acá mismo en el canal de TH-cam, activa las notificaciones y te saldrá, además TH-cam ahora cuenta con un apartado de en vivo o directos, donde puedes ver los directos pasados
Como adicional, esto se puede analizar facil pensandolo de esta forma, usando el reduce, estamos iterando 1 vez los usuarios (para crear el reduce) y 1 vez la otra lista que queremos marcar con el created_by_user. En cambio si usamos el find, estamos iterando potencialmente todos los usuarios en cada iteración de los elementos que queremos marcar. Es como pasar de tener 2 for uno abajo del otro, a dos for anidados. O sea, a grandes rasgos, el tiempo de ejecución pasa de 2*n a n^2. Esto quiere decir que la alternativa del find es exponencialmente mas lenta
Eso es lo malo de estos videos. No usan ciclos primitivos (2 for's y chan chan), y tiran de cosas que tambien son iteraciones, pero más rebuscadas (find, reduce, map, etc). No digo que esté mal usarlas, pero las explicaciones "primitivas" son importantes para transmitir el problema y su solución.
@@crayder03pienso igual y es por eso que al menos se debe tocar c o c++ leyendo un libro de análisis de algoritmos, bueno así lo aprendí en la universidad
Lo que comentas como primitivo es programación imperativa, las formas de iterar que mencionas entre paréntesis usan el paradigma de programación funcional que bajo a ciertos criterios se puede considerar mucho mejor que el imperativo, búscate las ventajas de la programación funcional @@crayder03
@@crayder03 Pues en mi caso me parece un reto lo que explica el video, no lo comprendí de primeras, pero estuve analizando el porqué y cómo funcionaba y luego comprendí. No considero que eso sea algo malo, uno ya se acostumbra que las explicaciones a veces no vienen con todo fácil y es trabajo de uno el analizarlo todo y así se aprende más.
no tanto porq al utilizar (find, reduce, map, etc) ya estaríamos con programación funcional y eso saca los for prácticamente, ya lo que si deberían leer como funcionan estas y cuando debemos utilizarlos @@crayder03
Podrías compartir cuanto tiempo te toma incluyendo el proceso de indexado con el reduce, para tener un panorama más cercano a solo usar find. Un saludo!
aqui es un problema de estructura de datos , es muy comun actualmente de usar arrays para todo , pero si vas a tener que realizar busquedas o multiples accesos es mejor usar Map u object dado que el acceso es de O(1) , en contra al O(n) esa es la idea , asi que cuando creas la structura de datos debes de pensar en eso y usar o un array o una estructura indexada ese es el problema , tmb puedes usar arboles ,binarios, monticulos , arboles balanceados , listas doble enlazadas ...dependiendo del tamaño y lo deseado multiples escrituras o lecturas o simplemente iteracion array ....
1. No es necesario hacer reduce. Puedes usar Map.
2. Funciona solo en casos de particiones heterógenas, donde cada valor es único.
3. El reduce debió haber sido agregado al benchmark.
4. Esta solución duplica el uso de memoria en largos datasets.
5. Usa un argumento función (thunk), exactamente lo mismo se puede hacer en un "for" simple. V8 tiene optimizaciones para for simples.
6. La solución no acepta case insensitve.
Como es reemplazable el reduce por un map?
map regresa una lista y lo que el esta formando es un objeto de {[id]: usuario}
supongo que podria hacer que el map haga pares de key:object y luego wrappearlo en Object.fromEntries, pero no hay mucha diferencia en "readability" o performance no?
Solo un apunte: al usar un objeto para crear el diccionario de usuarios, limitamos los tipos que podemos usar como clave (ya que todo se convierte a string). Una alternativa es usar el tipo Map, que tiene precisamente la finalidad de indexar objetos en base a una clave, y es más flexible que un objeto plano 🙂.
eso mismo fue lo que pense
Correcto!!
Yo también, pero entiendo el concepto que menciona en el ejemplo, en caso que requiera buscar por otra propiedad del objeto
Exactamente pensaba lo mismo.
Yo no entendí nada
Excelente, siempre invesigando sobre velocidad y ahorro. estas son realmente buenas practicas. Saludos Nico!!
Interesante dato. Yo lo uso. Desde que aprendi a programar busque alternativas mas legibles para mi codigo y performance. Buen tips
Wowo volvió :3 que alegria volver a ver a este grande !!!
Directo y práctico. Así los quiero 👍 gracias
Sos un maldito genio. Genio!!
Ya hacia falta los videos de este estilo al canal, se extrañan los de indole personal y de motivación. Son tu trademark!. P.D. recuerdo cuando hiciste este video cuando recien llegaste a nueva zelanda. Sin los efectos, ni background como ahora. Era simple pero muy orgánico y con una pieza de información reutil.
Cierto, yo llegue aquí por esos videos. Se extrañan
Si el indexado por id coincide con el índice del array original, no hace falta crear otro objeto cuyas llaves son la id, ya que la array original misma sirve para la búsqueda.
luego saca otro video para vender un curso sobre los hash table y además ese consoleTime deberia medir el reduce
@@csnzlatino En este caso el punto no es medir el reduce ya que se asume que este ya esta construido para ser usado multiples veces, por eso el ejemplo hace enfoque en el algoritmo de search que se supone va a ser utilizado en varias ocasiones
@@xdneos si quieres comparar con al método anterior, también tienes que medir el reduce.
Si yo pensé lo mismo. No tiene sentido crear el objeto usersIndexado si ya se puede usar el array original users!
Yo siempre hacia eso utilizando mapas, pero esta solución está mucho mejor y mas elegante.
Gracias por compartirla
Me gusta ver Hola mundo porque explica tan bien, muy pedagógico a mi parecer 👍
Por eso es común normalizar la data cuando viene de backend, normalizer por ejemplo puede transformar los array en hashTables y eso te salva la vida al momento de interactuar con la data.
Un apunte, un backend nunca debería enviar un array de miles de elementos al front.
@@jcuervasporque?
@@letthesuntalk cambiaré nunca por muy excepcionalmente. Es muy poco probable que el front necesite tanta información. Si vas a montar una tabla, solo necesitas tener los elementos que quepan en pantalla. Si renderizas en un navegador una tabla con cientos de filas el rendimiento va a ser malo, no digamos ya miles. Si es un gráfico, los datos deben llegar ya agregados, no vas a mostrar un gráfico de columnas con 100 columnas en un eje. En definitiva, el front no debería procesar datos, idealmente deben llegar ya procesados y se limitará a mostrarlos. Indexar un array tiene sentido en el backend, pero en el front es más usable un array de, como máximo, unas decenas de datos ya procesados
@@jcuervaspara esas excepciones se usa virtual scroll para que no penalice la performance del front
@@elektropunkk9835 aún así estas enviando más información de la necesaria. El payload de la petición puede ser muy grande. No digo que no se pueda hacer, pero en la mayor parte de los casos es mejor que el front tenga lo justo y necesario
El mejor explicandl gracias por este contenido
hola siento que soy un fracasado y pensé y no servía para nada pero me empezó a gustar la programación gracias a ti explicas de una manera comprensible, entendible pero la verdad aun no elijo a que lenguaje debería entrar pero gracias por hacer ala gente le guste la programación
usa javascript para aprender lo basico, los fundamentos, luego ver por un lenguaje orientado a objeto fuertemente tipado como JAVA. de ahi en adelante cualquier otro lenguaje sera pan comido, asi que profundiza estructura de datos y ejercicios de algoritmos, luego construye una web que haga algo valioso... no las tonteras de poke api. Saludos
En desarrollo te vas a sentir más "fracasado" aún, solo no te desanimes; que sentirse así es parte de la rama.
Yo estoy siguiendo el curso de Ultimate Python que dicta Nicolás, está muy bueno
Hola, pues llevo como desarrollandor junior 2 meses, creo que es verdad lo que comentan arriba, sigo sintiéndome fracasado y que no valgo aun cuando ya logro superar un problema difícil, lo que me ha ayudado es darme cuenta de que no soy el único, que es mejor aprender un poco cada día y seguir adelante, cuando menos lo esperes ya estarás muy avanzado en tu camino! Solo sigue adelante!
A todos nos pasa en algún momento eso de sentirnos fracasados, la cosa está en seguir aunque nos cueste, porque así tmb cuando nos sentimos inútiles, tmb nos sentimos increíbles cuando logramos aprender o superar algo q nos costó
Hay más variables a tener en cuenta, como en donde vive el índice, el tamaño del array de acuerdo a esto, cuál de los dos arrays a comprar crecerá más, uso mucho esta técnica pero hay que profundizar un poco más al usarla.
Buen video.
Esta muy bueno este video. Para la proxima deberias incluir el tiempo que tarda el indexado, asi se tendria una apreciacion mas justa de cuanto tarda en total toda la operacion....
Igual lo que más interesa es el tiempo de búsqueda pq la creación se debería hacer una vez o pocas veces
El indexado es lineal, el filter dentro del map es exponencial, siempre va a ser mejor lo lineal
Claro que es lineal, y claro que va a ser mejor.... Solo digo que se debe contar el tiempo de hacer el index como parte del proceso general!!
Qué es eso de lineal y exponencial?
@@juan7114 Un ciclo dentro de otro ciclo tiene una escala exponencial, porque la cantidad de iteraciones de los ciclos se multiplica
Un ciclo despues de otro (sin anidarse) tiene una escala lineal, porque las iteraciones se suman. Esto los hace mucho mas eficientes
Busca videos de notacion Big O
Wow muchas gracias por esta clase de vídeos.
como se extrañaba este tipo de contenidos
*Batallita del dev:*
Una vez hice un programa que trackeaba salas del primer resident evil y cada sala tenía una serie de coordenadas para pintar en el mapa la posición del jugador.
Cada segundo realizaba 60 ops de posicionamiento, pero en vez de crear una bound function o un mapa, hice un listado de if else, en la práctica funciona muy bien, pero realmente a veces me dan ganas de volver atrás y optimizar ese código.
Gracias por el consejo! Demasiado útil para reducir tiempos de búsqueda
Con el .find estás realizando bucles anidados por lo que el tiempo es O(n^2) en cambio con el .reduce baja a O(n) de ahí la mejora, pero ojo que a cambio la memoria aumenta O(n)
ahí la memoria aumentaría por el mapa que se esta creando de los usuarios? igual pensaba en eso, guardar en memoría un array de 10mil o más igual me parece arriesgado, yo le dejaría la pega de filtrar e indexar a la base de datos.
Y crear el indexado tampoco es gratis, lleva su tiempo y habrá que "recrearlo" o insertar en el lugar adecuado si se modifica, que tambien lleva su tiempo. Todo depende del caso particular a resolver.
Para ser justos, también debería haber tomado el tiempo de ejecución de la función reduce
YO lo veo viable para hacerlo en el servidor que no se haga en el front, porque hacerlo en el front, conlleva memoria por el cliente. Y en otro caso, creería que es más viable de inmediato filtrarlo desde la base de datos, así evitas traerse tanta data y traerla de una vez purgada.
callate
Alfin un buen uso práctico a reduce más que sumar todo los números
Muchas gracias justo lo que andaba buscando para optimizar resultados en mi sistemas
Hola, muy ameno tutorial, estoy aprendiendo rápido, Gracias!
Excelente explicación, buen vidio crack!, Saludos.
Oh guau, recomendando usar un método por sobre otro para eficiencia sin saber cómo están implementados, muy útil.
Ame, y tambien me encanto el Synthwave de fondo
Pero en ese caso deberías de agregar dentro del time() lo que estás haciendo con reduce() por que es un esfuerzo que haces por no usar find
También pensé lo mismo. Al final lo probé en el código, igualmente es mucho mas rápido agregando el reduce dentro del console.time. Yo hice la prueba con 2000 iteraciones; con el método find demora 33ms y con el reduce 7 ms.
@@jesushurtado1560 es correcto lo que dices, aunque de igual manera el punto de vista que comento es lo que se debía hacer en el ejemplo.
Está buenísimo esto chabón. Gracias
Excelente contenido. Muchas gracias.
Cada día me siento mas novato jaja mas videos como este porfa
Hola, Hola Mundo! 😃
Para tomar el tiempo real de la segunda opción con los usuarios indexados, no sería necesario mover el console.time encima del reduce? Ya que este es necesario para poder aplicar el userIndexado. Saludos
Es cierto, pero de todos modos va a ser mucho menos porque con el indexado, tenemos 1 loop que itera todos los usuarios para hacer el reduce, y otro loop que itera todos los elementos que queremos marcar con el created_by_user. O sea 2*n. En cambio usando el find, estamos haciendo una iteración de los usuarios por cada elemento que queremos marcar, o sea n iteraciones de n usuarios, n^2
en un caso de la vida real, probablemente sea una operación que ya tengas guardada en memoria, por lo que no se ejecutaría petición tras petición.
Totalmente de acuerdo @@Titere05 , no digo que esté mal la opción, al contrario, es genial. Simplemente que tampoco estamos mostrando el tiempo como debe ser, ya que deberia agregarse el tiempo para generar el indexado.
Saludos!
igual el indexado también cuesta un tiempo el cuál no se está contando, en un caso así donde puedes preindexar todos los usuarios no hay mucho problema pero en algo que tenga usuarios dinámicos no puedes hacer un único indexado
el caso sería exactamente el mismo, ya que la actualización del diccionario de usuarios se hace en tiempos de ejecución distintos al de la búsqueda en cuestión. La función de búsqueda irá a consultar el espacio en memoria que otra función mutó en un tiempo de ejecución distinto al de la función de búsqueda.
Es decir, en el momento en el que, por ejemplo, creas o eliminas usuarios, vas a actualizar la base de datos de usuarios e inmediatamente vas a modificar el indice para cuando alguien quiera consultarlo en otro momento.
Está genial el aporte 🤩
Aalaaamadr3333 como decimos en México!! 😮😮 ... Eres un crack!! ... Quiero aprender a programar y me urgeeee
Muy interesante, no nococia el concepto de hacer primero el indice del array y despues buscar mas rapido! Gracias!
Buen video, pero una observación. Esta implementación se vuelve ineficiente cuando tienes millones de usuarios para indexar (en términos de memoria), ya que cada usuario representa un hash que apunta a un lugar en la memoria y gestionarlos todos esos tiende a consumir mucha memoria muy rápido. Aunque en términos de búsqueda es muy eficiente computacionalmente (O(1)), para lograr una implementación eficiente tanto en memoria como en búsqueda, puedes utilizar un algoritmo simple de búsqueda binaria (manteniendo un array ordenado de elementos). Tener un array ordenado y buscar elementos representaría una complejidad de O(log(n)) en términos de cómputo al buscar elementos, pero consumiría solo O(n) en memoria. El único sacrificio sería que, en lugar de tener una complejidad de inserción de O(1), tendrías una complejidad de inserción de O(n) y aunque la búsqueda sería de O(log(n)) en lugar de O(1), esta complejidad es robusta y eficiente para prácticamente cualquier número industrial de usuarios u objetos.
Edit: Las complejidades arriba son para acceder e insertar un solo elemento del índice.
que pro, sube videos
También otra observación es que esta técnica es muy ineficiente cuando se tienen más procesos de escritura (como modificar o agregar) que de lectura dentro de estos objetos
carajo! ensename a entender esa eficiencia computacional por favor, o que libro recomiendas?
@@leonel1387 La página de Wikipedia de búsqueda binaria discute su complejidad en mas detalle. Lo mismo para la página de tabla de hash (se discute más a detalle en la página en inglés que en la que está en español)
Increíble... algún día profe .. algún día
gracias. podrias hacer un video de las funciones principales de lodash o un top
Una belleza!!! grande!
GRACIAAAASS AHORA TENGO QUE PONERLO EN 20 REPORTES DE UN SISTEMA WEB EN EL QUE TRABAJA MI EMPRESA, PERO ES NECESARIO
Que buen video y que buen polerón compa... saludos
Que buen nivel en algunos comentarios, siempre que veo vídeos así, los comentarios solo son aduladores o trollers, pero aquí hay nivel en tus seguidores, que bien, creo eso debe ser más satisfactorio...
Caraca! Que dica fantástica!!! Ganhou um inscrito brazuca! 🤘😁
está chida tu sudadera!!
Muchas gracias por tu explicacion, puedes por favor comprartirnos cual tema tienes instalado?
Excelente, buena idea para no usar los find dentro de un bucle
Muchas gracias
que buen tip y aporte!
Es una gran solución para reducir la complejidad en tiempo, pero se sacrifica complejidad en memoria que, en algunos casos, podria ser considerable.
bro y que sugieres en ese caso?
Es que esta mostrando un ejemplo básico (y pensado para que sea fácil de comprender), se asume que en la vida real no es así y que en vez de aplicar transformaciones con un map usaría un generador justamente para evitar el problema de la ram que mencionas.
volvistes genial
Cuánto es el costo de tiempo de la indexación?
Muy buen video y consejos, pero una salvedad: No mides el tiempo que tarda en crear el hashmap, diccionario o array asociativo. Eso tiene un coste tanto en memoria como tiempo (sí, es lineal, pero cuesta). La estrategia es ordenar la lista si vas a hacer varias consultas (de hecho, lo ideal es una inserción por orden), de este modo convertimos la búsqueda en log(n). El usar un índice es una estrategia similar a los índices de las bases de datos, pero tiene sus costes. El planteamiento es que los registros posean una estructura adecuada de inicio, el hecho de que sean random (que no es mal ejemplo para ilustrar lo que propones) nos hace saltar ese paso. Primero las estructuras adecuadas, luego los algoritmos.
cada problema está asociado a una estructura de datos:
iteración: lists, arrays
búsqueda: maps, trees
recursión: stacks, trees
desecho secuencial: queues
un map por ejemplo es demasiado rápido, pero consume mucha memoria, así que no es una opción para hardware o entornos con recursos muy limitados... en cambio un árbol es un poco más lento (pero más rápido que una lista), y consume sólo la memoria que necesita, así que se hace más interesante en esos dispositivos.
Habría que que analizar el impactó en memoria y tiempo de GC si es un proyecto productivo
En general, se asume que el precio de una buena tarjeta de memoria RAM es inferior al precio de un procesador, por ende, los desarrolladores prefieren sacrificar memoria que la sobre iteración de los procesos y ciclos, aunque en estos vídeos, uno queda con la falsa idea de que lo que se busca es la optimización en los tiempos de ejecución, cuando a un consumidor estandar ese dato le vale madres, para los proyectos que no sean de ciertos nichos inoficiosos.
Además, que en el vídeo tampoco se menciona nada sobre que es la manera en la cual se está ocupando la información en la RAM, y el modus operandi de la maquinaria en su arquitectura, lo que termina desarrollando mas o menos el mismo proceso que se está haciendo dentro del código con el uso de ciclos, pero de una manera más eficiente a cambio de consumir otro tipo de recursos de la máquina, al desarrollar operaciones matemáticas para obtener la ubicación de la información entre los espacios de la RAM, que en efecto, se van a encontrar considerablemente desperdiciados por la cantidad de posiciones en la ram que se encontrarán ocupadas y desperdiciadas al usar indexaciones que no sean numéricas y consecutivas.
@@1iamigo En JS, como en todos los lenguages con GC, usar memoria no solo es ocupar espacio de memoria sino que también hay que considerar el impacto en el procesamiento. Si no se tiene cuidado, los ciclos de GC pueden meter en algunos casos latencias esporádicas de varias decenas de ms y picos de usos de los procesadores. En un sistema productivo, la acumulación de estos ciclos se puede volver un problema mucho más grande del que muchos piensan. Es de hecho una de las causas más comunes de problemas de optimizacion.
@@javierolazaran7227 Así es, pero reitero, en el vídeo creo que se quedaron corto con respecto a estos temas, tampoco mencionaron nada sobre el orden de las funciones O(n)=n2 > 2n, etc...
Simplemente dicen, "no uses esto, hazlo así porque si, y porque así dio "resultado"."
Con esta manía, vamos a terminar con programadores que dicen ser pragmáticos, que solo van por resultados, pero que solo serán tan precoces como los mismos jefes, y serán igual de engreídos, vacíos y sin fundamentos.
Pero guenísimo video broo
Que buena idea, si me acuerdo voy a usarla la próxima
No dudo en que sea mucho mas rapido pero creo que tambien debio incluir el tiempo de crear el objeto de users indexado, de igual forma creo que es tremenda entrategia para mejorar el performance.
En el trabajo a veces se presentan ocaciones donde se requiere buscar un usuario no solo por su id, sino por otro atributo. Pars eso se usaría un "composite key" sería genial tener un tutorial de eso.
Saludos!
Muy interesante. Porque no más VIM?
buen aporte, por ahi estaria bueno calcular la complejidad (alg) y entender a fondo lo que pasa. Saludos y gracias!
Muy buen vídeo, me gusta muchisimo tu apariencia del VS Code, podrías decirnos que tema y fuente tienes instalado?
Un saludo!
El dioaaaaacheee que bueno, gracias brot
Gracias! Estava com problema de busca de dados em uma tabela que tem milhões de dados e, para essa consulta, tenho que recorrer em todas as linha afim de buscar o registro do usuário em específico.
muy buena, yo lo hago con forEach y Map
Que buena remera!
y ese hermoso tema cuál es? :o
Amo tu remera de demon slayer
Todo depende porque para eso existen los algoritmos de búsqueda que debemos conocer, depende mucho que estes buscando y tambien como esta el array
Probe el código porque me dio curiosidad cuanto tiempo agregaba el Reduce para crear el usersIndexado y no afecto el resultado, es muy eficiente 👏.
También me sirvió para ver la diferencia de potencia entre mi PC y la de Nicolas jajaja a el le tarda 0.4ms y a mi 4ms 😅😅
Me encantó!!
Vine por recomendacion del master hector de leon, excelente explicacion
Yo uso precisamente la indexación para la importación masiva en formato csv, que puede tener miles de registros; con eso, hasta un computador lento lo hace parecer todo una supercomputadora
Excelente maestro, podrias hacer el ejemplo pero con C#?
muy bueno, gracias!!
yo uso pandas con el iloc o loc, así si esta bien?
Gracias, pelón, buen tip
te amo pelón🤌
¿Cuánto fue el tiempo total sumando el tiempo del indexado?
Muchas gracias por el video, estaba buscando algo así, Me gustaría saber por qué dejaste de usar vim ?
Yo hago esto mismo pero instanciando un Map:
const usersMap = new Map()
Luego lo relleno:
users.forEach(user => usersMap.set(user.id, user))
Y para buscar un usuario:
const user = usersMap.get(id)
La del reducer la sabía, pero me pareció que lo natural era hacer un Map list, así que siempre me incliné por esta forma. Ahora bien, debería probar ambos casos a ver cuál performa mejor.
Habiendo hecho la tarea, pude comprobar que el método del reduce para indexar los datos es aproximadamente 2.5 veces más rápido que el de utilizar un Map list. Hice la prueba con 10 millones de usuarios y creando la lista con 10 millones de elementos. Con el reduce tarda mas o menos 3.77 segundos vs 9.37 segundos del Map.
Nico saludos desde ECUADOR cachai soy ecuatoriano bromeo seria bueno un curso de tu auditoria sobre php8 y mysql un crud en MVC Y USANDO OOP y saludos y que tal es estar en nueva zelanda
Que genial tu tema de vscode cual es ?
es HackTheBox by silofy
@@santiagomontoya9537 gracias amigo !
Buscar elementos en un array tiene una complejidad de O(n) en donde n es la longitud del array.
Buscar elementos en un hashmap O(1)
👌👌
Excelente, gracias
Y si cambiamos el reduce por foreach?
Interesante, mejora la performance. Pero justo al final del video me vino una pregunta, ¿Cuánto demora en hacer el indexado? Sumando el indexado al mapeo 0.445ms es menor a los 233.35ms?
Gracias y un saludo Nico, siempre viendo tus videos cuando tengo tiempo
lo ideal es hacer lo que haces una entity en redux con ngrx tener un diccionario donde la clave es el id y el valor el objeto y tener tambien un array con los ids para cuando es util el orden o devolver todos los elementos como un array.
Ok, pero entonces cuando dura el proceso de indexado? Porque deberías de calcular el tiempo que toma indexar + el tiempo que toma la búsqueda, y bueno, manejar la posibilidad de que el índice no exista, pero eso también pasa con el método find
estaba buscando este comentario, también saldría mas rápido usar un for que un map
Exacto, el timer hay que ponerlo más arriba e incluir dicho proceso
Completamente despreciable en comparacion a hacer la busqueda. Es comparar algo con O(N) contra (N**2). El indexado es mas costoso que una simple iteracion, pero sigue siendo una operacion O(N). Cuanto mas grande N, mas despreciable el valor (Comparar N**2 sobre N) la diferencia se hace mas grande cuanto mas grande N. Ejemplificado, para 1 millon de usuarios, el indexado costara una millonesima de lo que cuesta la busqueda con doble for, multiplicado por alguna constante, es decir, un numero muy pequeño
Un genio
La hostia, pepita de horo que necesitaba
Hola podrias hacer un tutorial sobre C# por favor
Y el coste del reduce?
se calcula en un tiempo de ejecución distinto al del algoritmo de búsqueda.
Muy bueno gracias
Buen video 👍