Soy bastante nuevo en JS y la primera vez que vengo aquí.
¿Cómo devuelves un objeto dentro de un array.reduce?
Entonces, por ejemplo: quiero encontrar el mínimo más bajo para el conjunto de datos de un día determinado. (Estoy usando una API de moneda como un conjunto de datos interesante para jugar). Los datos que obtengo son una matriz de objetos. Así que estaba usando un reduce para iterar día a día y encontrar el mínimo más bajo.
const lowestLow = historialCandlesFloatData.reduce((lowestLow,currentDay) => { if(currentDay.l < lowestLow.l){ return lowestLow = currentDay; }else return lowestLow; },);Eso funciona bien, pero también voy a necesitar que el índice del objeto se devuelva como el más bajo. Ahora sé que puede usar el índice como parte de reducir, y puedo consolar. registrar qué índice es el mínimo más bajo, pero no puedo averiguar cómo devolverlo junto con el mínimo como un objeto.
Podría usar un forEach, que parece funcionar bien, pero esta no parece la mejor manera de hacerlo y realmente me gustaría saberlo.
const findLow = ()=>{ let currentDayLow = 2; let dataIndex = 0; let datavalue = 0; historialCandlesFloatData.forEach((day)=>{ if(day.l < currentDayLow){ currentDayLow = day.l; datavalue = dataIndex; } dataIndex ++; }); return { lowestLow: currentDayLow, indexValue: datavalue, } }Si desea algo más/más que un valor de la matriz, se beneficiará al usar el segundo argumento de reduce : el valor inicial del acumulador. En este caso, el acumulador sería el "mejor" índice actual, por lo que el valor inicial del acumulador podría ser 0.
NB: en lugar de if else podría usar el operador condicional.
const lowestIdx = historialCandlesFloatData.reduce((lowestIdx, currentDay, i) => { return currentDay.l < historialCandlesFloatData[lowestIdx].l ? i : lowestIdx; }, 0); // Initial indexY luego con ese índice puedes recuperar el objeto correspondiente
const lowest = historialCandlesFloatData[lowestIdx];Para hacer eso con reduce , deberá hacer que el "acumulador" que pasa sea un objeto con el valor y el índice en él. (Er, o simplemente devuelva el índice y luego utilícelo para obtener el elemento, como mostró trincot ). Por ejemplo:
const lowestLow = historialCandlesFloatData.reduce((lowestLow, currentDay, index) => { return !lowestLow || currentDay.l < lowestLow.entry.l ? { entry: currentDay, index } : lowestLow; }, null);Ejemplo en vivo:
const historialCandlesFloatData = [{ l: 4 }, { l: 1 }, { l: 3 }, { l: 7 }]; const lowestLow = historialCandlesFloatData.reduce((lowestLow, currentDay, index) => { return !lowestLow || currentDay.l < lowestLow.entry.l ? { entry: currentDay, index } : lowestLow; }, null); console.log(lowestLow);Alternativamente, puede hacer que el acumulador sea una versión aumentada de los objetos de la matriz al agregarle el índice:
const lowestLow = historialCandlesFloatData.reduce((lowestLow, currentDay, index) => { return !lowestLow || currentDay.l < lowestLow.l ? { ...currentDay, index } : lowestLow; }, null);Ejemplo en vivo:
const historialCandlesFloatData = [{ l: 4 }, { l: 1 }, { l: 3 }, { l: 7 }]; const lowestLow = historialCandlesFloatData.reduce((lowestLow, currentDay, index) => { return !lowestLow || currentDay.l < lowestLow.l ? { ...currentDay, index } : lowestLow; }, null); console.log(lowestLow); Pero no soy partidario de usar reduce con funciones ad hoc, sobre todo porque es muy fácil tropezarse con él al olvidarse de proporcionar un valor inicial (cuando sea necesario), olvidarse de hacer un return en todas las rutas de código, etc. A menos que está haciendo programación funcional con funciones reductoras predefinidas y reutilizables, prefiero bucles simples:
let lowestLow = null; let lowestIndex; for (let index = 0; index < historialCandlesFloatData.length; ++index) { const entry = historialCandlesFloatData[index]; if (!lowestLow || entry.l < lowestLow.l) { lowestLow = entry; lowestIndex = index; } }Ejemplo en vivo:
const historialCandlesFloatData = [{ l: 4 }, { l: 1 }, { l: 3 }, { l: 7 }]; let lowestLow = null; let lowestIndex; for (let index = 0; index < historialCandlesFloatData.length; ++index) { const entry = historialCandlesFloatData[index]; if (!lowestLow || entry.l < lowestLow.l) { lowestLow = entry; lowestIndex = index; } } console.log(lowestLow);Sí, en este caso es más código, pero es posible que lo encuentre más claro y/o menos propenso a errores, especialmente si recién está comenzando.
¿Por qué no agrega una nueva propiedad al objeto usando el operador de extensión de JavaScript ... ? Por ejemplo, así:
const lowestLow = historialCandlesFloatData.reduce((lowestLow, currentDay, idx) => { if(currentDay.l < lowestLow.l){ return { ...currentDay, idx: idx, }; } else { return lowestLow; } }, // Initial value { l: historialCandlesFloatData[0].l + 1 } ); // Now you can access the index like so const index = lowestLow.idx;