En primer lugar, disculpas si esto normalmente es algo simple, pero no tengo mucha experiencia en JS. Estoy tratando de hacer algunos gráficos en Plotly.js para un sitio de trabajo que actualmente contiene JSON sin formato. Tenemos un JSON en el formato:
stuff = [{"name": "shark", "location": "somewhere", "number":10}, {"name": "shark", "location": "somewhereelse", "number":50}, {"name": "shark", "location": "somewhere", "number":25}, {"name": "turtle", "location": "anotherplace", "number":1}, {"name": "elephant", "location": "greatplace", "number":50}, {"name": "elephant", "location": "greatplace", "number":75}Y necesito que el resultado se vea así:
computed = [{"name":"shark", "location":"somewhere", "number":35}, {"name":"shark", "location":"somewhereelse", "number":50}, {"name":"turtle", "location":"anotherplace", "number":1}, {"name":"elephant", "location":"greatplace", "number":125}Donde todos los nombres se agrupan por ubicación y se suman todos los números de ese grupo. Entonces es este JSON calculado el que usaré para graficar con Plotly.js con algunas funciones que ya he creado.
Creo que puedo simplificar el problema como:
forEach((item) => { x.push(item['location'] y.push(y += stuff.number where stuff.location === x[-1]) }Pero esto también significa que obtendré la misma cantidad de filas que en las cosas, solo calculadas y graficadas. Me temo que no puedo entenderlo más.
Cualquier ayuda sería muy apreciada.
Simplemente recorriendo la matriz original y agregando los elementos a una nueva matriz a menos que ya se hayan agregado, o simplemente agregar el number será el truco aquí. Aquí está el definido:
var computed: any = []; for(var element of stuff){ let computedElement = computed.find((ele: { location: string; }) => ele.location == element.location); if (computedElement){ computedElement.number += element.number; } else{ computed.push(element); } }En primer lugar, json comienza con {} y no con []. Su objeto es un objeto javascript. Hice una función muy larga a continuación:
const stuffList = [ {"name": "shark", "location": "somewhere", "number":10}, {"name": "shark", "location": "somewhereelse", "number":50}, {"name": "shark", "location": "somewhere", "number":25}, {"name": "turtle", "location": "anotherplace", "number":1}, {"name": "elephant", "location": "greatplace", "number":50}, {"name": "elephant", "location": "greatplace", "number":75} ] //extract all available location const locations = stuffList.map( stuffItem => { return stuffItem.location }) const filteredStuff = locations.map( location => { const number= stuffList.map( stuffItem => { if(stuffItem.location === location) { return stuffItem.number } return 0 }).reduce( (a, b) => a + b)// total all the numbers of mathcing location //get the first newStuffItem value equals to location const [filteredStuffItem] = stuffList.map( stuffItem => { if(stuffItem.location === location) { return { name: stuffItem.name, location, number } } }).filter( stuffItem => { return stuffItem?.location === location }) return filteredStuffItem }) const newStuffList = filteredStuff.filter((thing, index) => { const _thing = JSON.stringify(thing); return index === filteredStuff.findIndex(obj => { return JSON.stringify(obj) === _thing; }) }); console.log(newStuffList)O la magia de Deepak en javascript:
const stuff = [ {"name": "shark", "location": "somewhere", "number":10}, {"name": "shark", "location": "somewhereelse", "number":50}, {"name": "shark", "location": "somewhere", "number":25}, {"name": "turtle", "location": "anotherplace", "number":1}, {"name": "elephant", "location": "greatplace", "number":50}, {"name": "elephant", "location": "greatplace", "number":75} ] var computed = []; for(var element of stuff){ let computedElement = computed.find((ele) => ele.location == element.location); if (computedElement){ computedElement.number += element.number; } else{ computed.push(element); } } console.log(computed)Lo siento por no responder a esto antes, y gracias a los que comentaron. Por alguna razón, no pude hacer funcionar las otras soluciones sugeridas, pero ver otra perspectiva sobre la lógica necesaria me ayudó a resolverlo.
if (!label.includes(item['specimen'] + ':' + item['well_label'] + ':' + item['run'] + ':' + item['group'])) { label.push(item['specimen'] + ':' + item['well_label'] + ':' + item['run'] + ':' + item['group']) x.push(item['date']) y.push(item['sum']) } else { var indx = label.indexOf(item['specimen'] + ':' + item['well_label'] + ':' + item['run'] + ':' + item['group']) let summed = y[indx] + item['sum'] y.splice(indx, 1, summed)Básicamente, esto creó algo similar a una clave compuesta y empuja los datos iniciales para agregarlos a la lista de etiquetas y luego los datos a las listas relevantes. Si esa clave compuesta vuelve a aparecer, el valor se actualiza con el método de empalme.
El único problema es que debido a que estas listas no están vinculadas de ninguna manera que los datos que se ingresan en ellas, existe una rara posibilidad de que la etiqueta correcta y los datos no coincidan, pero después de muchas pruebas, lo solucioné y funciona.
Nuevamente, gracias a los comentaristas anteriores que ayudaron.