How to group an object array in javascript (Angular)

Asked

Viewed 7,208 times

2

How to read an array of objects and returns only objects that contain the same value in several attributes? I made this object array as an example.

var arrayDeObjetos = [
  {"dia":1 , "desc":"Nigth","mes":1},
  {"dia":1 , "Descricao":"Brilha","mes":1},
  {"dia":2 , "desc":"Urna","mes":2},
  {"dia":3 , "Descricao":"Covas","mes":1},
  {"dia":2 , "desc":"Mario Corvas","mes":1},
  {"dia":4 , "Desc":"Estrelas","mes":2}
];

In this Array I have several objects I wanted to group all and a new array that contains one object with all that contains dia = 1 and mes = 1 another object that contains all with dia = 2 and mes = 2 The end result has to be something like

var resultado = [
  [
    {"dia":1,"mes":1,"desc":"descricao AQI"},
    {"dia":1,"mes":1,"desc":"Outra desc"}
  ],
  [
    {"dia":2,"mes":2,"desc":"outro mes"},
    {"dia":1,"mes":1,"desc":"outra coisa"}
  ]];
  • 1

    There are "N" ways to do this, from iterations with foreach or for, or using the method map() > more information from him here: W3schools - Map. Or also, use a very good library that will make your life easier, it’s called Linqjs.

  • The result is the same or you meant that in each index of the array contains objects of the same day and same month?

  • Joao, in the resultado you have in question dia 1 and mês 1 in both... it’s a mistake?

  • @Sergio was my typo

  • Okay. Can you correct the question? I would like to give an answer but I want to be sure of the outcome you expect.

4 answers

1

One way is by using the Javascript Filter to find only the values you need and insert them into a new array using the push, See the example below:

var arrayDeObjetos = [
  {"dia":1 , "desc":"Nigth","mes":1},
  {"dia":1 , "Descricao":"Brilha","mes":1},
  {"dia":2 , "desc":"Urna","mes":2},
  {"dia":3 , "Descricao":"Covas","mes":1},
  {"dia":2 , "desc":"Mario Corvas","mes":1},
  {"dia":4 , "Desc":"Estrelas","mes":2}
];

var novoArray = [];

novoArray.push(filtrarArray(arrayDeObjetos, 1, 1));
novoArray.push(filtrarArray(arrayDeObjetos, 2, 2));

console.log(novoArray);

function filtrarArray(array, dia, mes) {
  return array.filter(function(val) {
    return val.dia === dia && val.mes === mes;  
  });
}

1


If the object array is too extensive, you can separate an array of nonduplicated objects by mapping the days and months and then filter based on what was discovered.

var arrayDeObjetos = [
  {"dia":1 , "desc":"Nigth","mes":1},
  {"dia":1 , "Descricao":"Brilha","mes":1},
  {"dia":2 , "desc":"Urna","mes":2},
  {"dia":3 , "Descricao":"Covas","mes":1},
  {"dia":2 , "desc":"Mario Corvas","mes":1},
  {"dia":4 , "Desc":"Estrelas","mes":2}
];

Will become objetosASeparar:

objetosASeparar = [
  {dia: 1, mes: 1},
  {dia: 2, mes: 2}
]

So if there is day 3 and month 3, day 4 and month 4 so on, all will be filtered into a new object.

var arrayDeObjetos = [
  {"dia":1 , "desc":"Nigth","mes":1},
  {"dia":1 , "Descricao":"Brilha","mes":1},
  {"dia":2 , "desc":"Urna","mes":2},
  {"dia":3 , "Descricao":"Covas","mes":1},
  {"dia":2 , "desc":"Mario Corvas","mes":1},
  {"dia":4 , "Desc":"Estrelas","mes":2}
];

// obter um array de objetos com dia e mes não duplicados
var objetosASeparar = [];
arrayDeObjetos.filter(item => item.dia == item.mes).map(function(item){
  if(item.dia == item.mes){
    return {
      dia: item.dia,
      mes: item.mes
      }
  }
}).forEach(function(a){
  if (objetosASeparar.length == 0) objetosASeparar.push(a);
  objetosASeparar.forEach(function(b){
    if (b.dia !== a.dia && b.mes !== a.mes)
      objetosASeparar.push(a);
  });
});

// filtrados com base nos objetos descobertos
var novoObjeto = {};
objetosASeparar.forEach(function(a,i){
    novoObjeto[i] = arrayDeObjetos.filter(b => a.dia == b.dia && a.mes == b.mes);
});

console.log(novoObjeto);

0

Do

var objetos = [
   {"dia":1 , "desc":"Nigth","mes":1},
   {"dia":1 , "Descricao":"Brilha","mes":1},
   {"dia":1 , "desc":"Nigth","mes":1},
   {"dia":2 , "desc":"Urna","mes":2}
]

var meuNovoArray = [];

angular.forEach(objetos, function(objeto)){
     if(objeto.dia === 1){
         menuNovoArray.push(objeto) //adiciona o obj nesse seu novo array
     }
}

Then just give a console.log(myNovoArray) that will work.

0

This type of operation is called map reduce, in javascript every array has the operation reduce for these cases. Here are 2 examples of how to use it in your case.

Utilizing Object:

Object.values([
    {"dia":1 , "desc":"Nigth","mes":1},
    {"dia":1 , "Descricao":"Brilha","mes":1},
    {"dia":2 , "desc":"Urna","mes":2},
    {"dia":3 , "Descricao":"Covas","mes":1},
    {"dia":2 , "desc":"Mario Corvas","mes":1},
    {"dia":4 , "Desc":"Estrelas","mes":2}
  ].reduce(function(prev, item) {
    var key = item.dia * 100 + item.mes;
    prev[key] = prev[key] || [];
    prev[key].push(item);
    return prev;
  }, {})
);

Utilizing Array:

[
  {"dia":1 , "desc":"Nigth","mes":1},
  {"dia":1 , "Descricao":"Brilha","mes":1},
  {"dia":2 , "desc":"Urna","mes":2},
  {"dia":3 , "Descricao":"Covas","mes":1},
  {"dia":2 , "desc":"Mario Corvas","mes":1},
  {"dia":4 , "Desc":"Estrelas","mes":2}
]
.reduce(function(prev, current) {
    var index = prev.findIndex(function(j) { return j.dia == current.dia && j.mes == current.mes});
    if (index < 0) {
        index = prev.length;
        prev.push({
            dia: current.dia,
            mes: current.mes,
            lista: []
        });
    }
    prev[index].lista.push(current);
    return prev;
}, [])
.map(function(item){
    return item.lista;
});

Although more complex the method using array should be more efficient than the method using object.

Observing Do not index the day and month array, e.g.: array[mes*100 + day], because in the javascript language it will create all positions in the array until it reaches the specified value.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.