const{Transform}=require('stream');const camelStream =newTransform({transform(chunk, callback){const data = chunk.toString(); data.split(" ").map((word)=>{this.push(word.charAt(0).toUpperCase()+ word.slice(1));});}});process.stdin.pipe(camelStream).pipe(process.stdout);```
Esta bien muy simplificado. Solo que no seria camelCase ya que la primer palabra tambien te la coloca como mayuscula. Modificaria tu codigo de esta manera:
El código ya está bien, de hecho hay dos tipos de camelCase
UpperCamelCase
lowerCamelCase
El primero es el que enuncia el compañero del comentario de abajo.
El propósito de tener distintos tipos de streams no solo es simplificar el código, tienen pequeñas diferencias en su objetivo.
Tipos de streams
Hay cuatro tipos fundamentales de streams en Node.js
Writable: streams en los que los datos pueden ser escritos.
Readable: streams en los que los datos pueden ser leídos.
Duplex: streams que pueden ser leídos y escritos.
Transform: Duplex streams que pueden modificar o transformar los datos cuando son escritos o leídos.
Mi Reto desglosado
const{Transform}=require('stream')/** ingresa un string y convierte el primer
* carácter a mayúscula
*/constupperFirst=text=>{//obtiene primer letra y convierte a mayúsculalet first = text.charAt(0).toUpperCase()//el string a partir de la segunda letralet rest = text.slice(1)//unión primer letra + restoreturn first + rest
}const transformStream =newTransform({transform(chunk, encoding, callback){//la cadena de entrada en stringconst strChunk = chunk.toString()//cadena en minúsculasconst lowerChunk = strChunk.toLowerCase()//array separado por espacio en blancoconst arrayChunk = lowerChunk.split(' ')/**
* creación de un nuevo array con camelCase
* si i (index) es 0 se retorna la primer
* palabra sin cambios, si no se cambia la
* primer letra de la palabra a mayúscula
*/const arrayCamel = arrayChunk.map((word,i)=>{return i ===0? word :upperFirst(word)})//se junta el array anterior y listoconst camelCase = arrayCamel.join('')this.push(camelCase)//finaliza la el flujo para esta chunkcallback()}})process.stdin.pipe(transformStream).pipe(process.stdout)
Mi reto simplificado
const{Transform}=require('stream')constupperFirst=text=>{return text.charAt(0).toUpperCase().concat(text.slice(1))}const transformStream =newTransform({transform(chunk, encoding, callback){const camelCase = chunk
.toString().toLowerCase().split(' ').map((word, index)=>{return index ===0? word :upperFirst(word)}).join('')this.push(camelCase)callback()}})process.stdin.pipe(transformStream).pipe(process.stdout)
se puede optimizar más pero no se vería bien en este cuadrito de los aportes, esto lo hago con la finalidad de ayudar un poco a entender el código a los que no entienden muy bien :).
Gracias! :) ya pude comprender un poco más
@Laurapregonero super, que bueno que el ejemplo te ayudo :)
Aquí está mi solución, nada extraño y haciendo uso de código normal:
Evidencia:
Muy top tu código compañero!!! Gracias:)
Gracias Máster! Excelente!
Muy limpio.
realmente no conocía mucho del split y el slice.
Aún me falta practicar bastante.
Debes sentirte orgulloso de tu talento!
Esta web https://jsperf.com/js-camelcase/5 me sirvio mucho, no solo para ver los distintos casos, sino tambien para saber cual puede ser la mas optima.
Esta ha sido mi respuesta favorita
En mi opinión, es un poco confusa la explicación pues parece que se dice que se dice que Duplex y Transform sirven para lo mismo, sólo que el último tiene una sintaxis más sencilla. A mí me gustó esta explicación:
.
"It’s important to understand that the readable and writable sides of a duplex stream operate completely independently from one another. This is merely a grouping of two features into an object.
.
A transform stream is the more interesting duplex stream because its output is computed from its input."
.
Fuente:
Si, ese artículo es clave para entender esto bien. Gracias!
Tienes razón, es claro que cada tipo de Stream tiene su razón de ser y se debe usar en el momento que corresponda.
Un poco de información extra que me ayudo a comprender mejor los Streams node-js-streams-everything-you-need-to-know
Gracias!! :D
Muchacho ahi dejo mi solución al reto y me lógica en un comentario !!!
Escucho aportes
/*
Challenge
Usando Streams crea una función en Node que reciba una cadena de texto y la convierta en camel case usando streams.
"hola como estas"
"holaComoEstas"
¿Que quiero?
Una función stringToCamelCase() que cuando reciba un string cualquiera lo convierta en CameCase, usando Streams.
El proceso para hacerlo realidad.
1. Recibo una cadena de texto.
2. Detecto los separadores: espacios en blanco o guiones que separan las palabras.
3. A la primera letra de la palabra que está a la derecha del separador la paso a mayusculas.
4. Creo un nuevo string donde elimino el separador.
5. Retorno la nueva cadena de texto.
Una vez hecho esto creare un WritableStream desde donde consumire los datos y los devolveré transformados.
*/const{Writable}=require("stream");functionstringToCamelCase(string){//"Hola-soy-una-persona-chevere"const whiteSpaceAndLetter =/(?<=[\-. ])\w/g;const separatorString =/[\-. ]/g;constupperCaseCharacterFound=(characterFound)=> characterFound.toUpperCase();let stringTransformed = string.replace(whiteSpaceAndLetter, upperCaseCharacterFound); stringTransformed = stringTransformed.replace(separatorString,"");return stringTransformed
}const writableStream =newWritable({write(chunk,encoding, callback){const stringChunk = chunk.toString()console.log(stringToCamelCase(stringChunk));callback();}});process.stdin.pipe(writableStream);
Yo resolví el reto de esta forma pero me quedó un pequeña duda, en todo caso no me gusta que las cosas funcionen sin saber el porqué de algo y es por que en este caso no tuve que ejecutar el callback para que funcionara, incluso si ejecuto el callback me genera un error. Alguien entiende el porqué? :D
La función callback es llamada para indicar que se terminó y que el siguiente "middleware" puede ejecutarse, es algo confuso, tal vez en lugar de llamarlo callback podrías llamarlo next. Me parece raro que te fallé al llamar el callback, no sé que error te pueda dar.
Mira este comentario de stackoverflow para entender mejor cómo funcionan los middlewares, que en esencia es lo que pasa aquí.
Muchas gracias!, me quedó todo más claro :D
const{Transform}=require("stream");const transformStream =newTransform({transform(chunk, enconding, callback){let camel = chunk.toString().toLowerCase()let tr_camel = camel.split(' ')letCamelCase=''for(let index =0; index < tr_camel.length; index++){CamelCase=CamelCase.concat( tr_camel[index].charAt(0).toUpperCase()+ tr_camel[index].slice(1))}this.push(CamelCase);callback();}});process.stdin.pipe(transformStream).pipe(process.stdout);
const CamelCaseChallenge = new Transform({
transform(chunk, encoding, cb){
this.push(Camel(chunk.toString()));
cb();
}
});
//uso del callback
function Camel(str){
let camelcase = str.split(" ").map((word) => {
return word.charAt(0).toUpperCase() + word.slice(1);
});
return camelcase.join('');
};
process.stdin.pipe(CamelCaseChallenge).pipe(process.stdout);
/**
* en una nueva funcion realizar lo siguiente:
*
* 1ero = split me guarda por el caracter que detecte y me crea
* un array que luego map recorre cada espacio de dicho array de strings
* donde el chatAt(0) leera en la posicion 0 de cada string
* por cada espacio en el array donde en dicha posicion convertira
* la letra 0 en mayuscula con toUpperCase().
*
* (0 porque se empieza desde 0 en programacion).
*
* 2do = luego se le concatena con slice que toma el valor que va a
* retirar de la cadena, como split convierte el texto en un slot
* el slice elimina el slot creado dejandolo void.
*
* 3ero = se retorna todo el proceso con join que unifica los espacios
* creados en un array que en este caso el array lo creo el split.
*
* OJO>>el join solo combina strings, no se si numeros.
*
* proceso paso a paso:
*
* parte-1 el texto=
* hola mundo
*
* ////////////////////////////////////////////////////////////
*
* parte-2 el split trabajando =
* split(" ");
* [hola], [ ], [mundo];
*
* resultado = ["hola"," ","mundo"] array con un nuevo slot.
*
* ////////////////////////////////////////////////////////////
*
* parte-3 el slice eliminando el espacio del array:
* slice(1)
* ["hola"," ","mundo"]
* 0 1 2
* ["hola","mundo"] ["hola","mundo"]
* 0 2 => termina siendo 0 1
*
* ////////////////////////////////////////////////////////////
*
* parte-4 el join combinando el array de strings :
* el array:
* ["hola","mundo"]
*
* join("") => ojo en la documentacion del metodo join el aparece
* asi join(), lo que significa que unira con todo y
* "las comas invisibles del array",
*
* el join que contenga algo tipo => join ("/") me va a unir
* los slot o espacios con el slash.
*
* en este caso:
*
* join("") >> sin separar para que no los una asi sin mas
*
* join("")
* ["hola","mundo"]
*
* RESULTADO = HolaMundo
*
*
*
*
*/
Esta es mi solución, tambien pudedo recalcar que el formato de texto donde la primera letra de la primera palabra tambien es mayúscula se llama PascalCase y esta es camelCase
const{Transform}=require('stream');let data ='';const transformStream =newTransform({transform(chunk, encoding,callback){ data = chunk.toString().trim().split(' '); data = data.reduce((total, word)=>{return total + word.charAt(0).toUpperCase()+ word.slice(1)}, data[0].toLowerCase())console.log(data);callback();}});process.stdin.pipe(transformStream).pipe(process.stdout);