Actualmente tengo una matriz que tiene la siguiente estructura:

data = [
{
  time: 100,
  info: [{
    name: "thing1",
    count: 3
  }, {
    name: "thing2",
    count: 2
  }, {
  }]
},
{
  time: 1000,
  info: [{
    name: "thing1",
    count: 7
  }, {
    name: "thing2",
    count: 0
  }, {
  }]
}
];

Pero me gustaría reestructurar la matriz para obtener algo como esto:

data = [
{
  name: "thing1",
  info: [{
    time: 100,
    count: 3
  }, {
    time: 1000,
    count: 7
  }, {
  }]
},
{
  name: "thing2",
  info: [{
    time: 100,
    count: 2
  }, {
    time: 1000,
    count: 0
  }, {
  }]
}
];

Entonces, básicamente, la clave tendría que cambiarse de tiempo a nombre, pero la pregunta es cómo. De otras publicaciones he deducido que usar la función de mapa podría funcionar, pero dado que otras publicaciones tenían ejemplos hacia y desde diferentes estructuras, todavía no estoy seguro de cómo usar esto.

0
Oompaloompa 28 may. 2020 a las 03:50

4 respuestas

La mejor respuesta

Sin embargo, hay varias maneras de lograr esto, la idea clave será realizar un bucle anidado de los elementos data y sus elementos (anidados) info. Hacer eso permite que su algoritmo "visite" y "asigne" cada pieza de datos de entrada, a un valor correspondiente en la matriz resultante.

Una forma de expresar eso sería utilizar llamadas anidadas a Array # reduce () para obtener primero una asignación de: name -> {time,count}

Esa asignación resultante se pasaría a una llamada a Object.values () para transformar los valores de esa asignación en la matriz requerida.

El funcionamiento interno de este proceso de mapeo se resume en la siguiente documentación:

const data=[{time:100,info:[{name:"thing1",count:3},{name:"thing2",count:2},{}]},{time:1e3,info:[{name:"thing1",count:7},{name:"thing2",count:0},{}]}];

const result = 
/* Obtain array of values from outerMap reduce result */
Object.values(

  /* Iterate array of data items by reduce to obtain mapping of
  info.name to { time, count} value type */
  data.reduce((outerMap, item) => 
  
    /* Iterate inner info array of current item to compound 
    mapping of info.name to { time, count} value types */
    item.info.reduce((innerMap, infoItem) => {
  
      if(!infoItem.name) {
        return innerMap
      }
  
      /* Fetch or insert new { name, info } value for result 
      array */
      const nameInfo = innerMap[ infoItem.name ] || { 
        name : infoItem.name, info : [] 
      };

      /* Add { time, count } value to info array of current 
      { name, info } item */
      nameInfo.info.push({ count : infoItem.count, time : item.time })

      /* Compound updated nameInfo into outer mapping */ 
      return { ...innerMap, [ infoItem.name] : nameInfo }
      
  }, outerMap), 
  {})
)

console.log(result)

¡Espero que eso ayude!

1
Dacre Denny 28 may. 2020 a las 01:28

El enfoque que tomaría sería usar un objeto de mapeo intermedio y luego crear la nueva matriz a partir de eso.

const data = [{time: 100, info: [{name: "thing1", count: 3}, {name: "thing2", count: 2}, {}]}, {time: 1e3, info: [{name: "thing1", count: 7}, {name: "thing2", count: 0}, {}]} ];

const infoByName = {};

// first loop through and add entries based on the name
// in the info list of each data entry. If any info entry
// is empty ignore it
data.forEach(entry => {
  if (entry.info) {
entry.info.forEach(info => {
  if (info.name !== undefined) {
    if (!infoByName[info.name]) {
      infoByName[info.name] = [];
    }      
    infoByName[info.name].push({
      time: entry.time,
      count: info.count
    });
   }
});
  }
});

// Now build the resulting list, where name is entry
// identifier
const keys = Object.keys(infoByName);
const newData = keys.map(key => {
  return {
 name: key,
 info: infoByName[key]
  };
})

// newData is the resulting list
console.log(newData);
0
Andre M 28 may. 2020 a las 01:34

Bueno, el otro tipo publicó una solución mucho más elegante, pero yo la resolví, así que pensé que también podría publicarla. :)

var data = [
    {
      time: 100,
      info: [{
        name: "thing1",
        count: 3
      }, {
        name: "thing2",
        count: 2
      }, {
      }]
    },
    {
      time: 1000,
      info: [{
        name: "thing1",
        count: 7
      }, {
        name: "thing2",
        count: 0
      }, {
      }]
    }
    ];
    
    var newArr = [];
    
    const objInArray = (o, a) => {
      for (var i=0; i < a.length; i += 1) {
        if (a[i].name === o)
          return true;
      }
      return false;
    }
    
    const getIndex = (o, a) => {
      for (var i=0; i < a.length; i += 1) {
        if (a[i].name === o) {
          return i;
        } 
      }
      return false;
    }
    
    const getInfoObj = (t, c) => {
    
       let tmpObj = {};
       tmpObj.count = c;
       tmpObj.time = t;
       return tmpObj;
      
    }
    
    for (var i=0; i < data.length; i += 1) {
      let t = data[i].time;
      
      for (var p in data[i].info) {
        if ("name" in data[i].info[p]) {
        
        if (objInArray(data[i].info[p].name, newArr)) {
          let idx = getIndex(data[i].info[p].name, newArr);
          let newInfoObj = getInfoObj(t, data[i].info[p].count);
          newArr[idx].info.push(newInfoObj);
        } else { 
          let newObj = {};
          newObj.name = data[i].info[p].name;
          let newInfo = [];
          let newInfoObj = getInfoObj(t, data[i].info[p].count);
          newInfo.push(newInfoObj);
          newObj.info = newInfo;
          newArr.push(newObj);
         }}
      }
    }   
     
    console.log(newArr);
0
Brian Patterson 28 may. 2020 a las 01:58

Intente usar Object.keys () para obtener la clave

-2
Moukim hfaiedh 28 may. 2020 a las 01:12