Zoeken op website

javascript - Hoe groepeer ik een array van objecten op subobject?


Ik gebruik TypeScript voor de back-end van een webapplicatie, en ik heb de intersection types erg handig gevonden voor het maken van efficiënte SQL-queries. In feite, als ik de volgende tabellen heb:

User

userId: number
userEmail: string

Post

postId: number
userId: number (FK)
postBody: string

Ik kan eindigen met een intersectietype (User & Post) dat er zo uitziet:

{
  userId: number;
  userEmail: string;
  postId: number;
  postBody: string;
}

Dit betekent dat ik dit type kan gebruiken om de rijen die ik terugkrijg van een gecombineerde select-query weer te geven.

Het probleem is dat ik vervolgens de gegevens op de webserver moet uit elkaar halen. Ik moet iteratieve code schrijven om ze voor elke query te groeperen, en dit kan repetitief worden. Dit is het soort transformatie dat ik probeer te krijgen:

In :

[
  {
    userId: 1,
    userEmail: '[email ',
    postId: 1,
    postBody: 'User 1\'s first post',
  },
  {
    userId: 1,
    userEmail: '[email ',
    postId: 2,
    postBody: 'User 1\'s second post',
  },
  {
    userId: 2,
    userEmail: '[email ',
    postId: 3,
    postBody: 'User 2\'s first post',
  },
]

Uit :

[
  {
    userId: 1,
    userEmail: '[email ',
    posts: [
      {
        postId: 1,
        postBody: 'User 1\'s first post',
      },
      {
        postId: 2,
        postBody: 'User 1\'s second post',
      }
    ],
  },
  {
    userId: 2,
    userEmail: 'User 2\'s email',
    posts: [
      {
        postId: 3,
        postBody: 'User 2\'s first post',
      }
    ]
  }
]

Ik probeer een functie te bedenken die ik kan gebruiken om dit dynamisch te doen, misschien door de collectie, een array van bovenliggende sleutelnaam en de naam van de onderliggende collectie door te geven. Ik eindigde met een onsuccesvolle functie met de volgende handtekening: function group(coll: Array<any>, parentKeys: Array<string>, childCollName: string): Array<any>;

Ik vroeg me af of iemand me zou kunnen helpen met het implementeren hiervan.

Tot nu toe heb ik al geprobeerd Lodash te gebruiken. Echter, de groupBy-functie lijkt niet te kunnen bepalen dat de subobjecten gelijk zijn en geeft me in dit voorbeeld nog steeds een array van drie objecten.

Antwoord #1

Wat dacht je van iets proberen zoals hieronder, in een lus gaan en objecten creëren

var arry = [
    {
        userId: 1,
        userEmail: '[email ',
        postId: 1,
        postBody: 'User 1\'s first post',
    },
    {
        userId: 1,
        userEmail: '[email ',
        postId: 2,
        postBody: 'User 1\'s second post',
    },
    {
        userId: 2,
        userEmail: '[email ',
        postId: 3,
        postBody: 'User 2\'s first post',
    },
];

function createPost(obj) {
    post = {};
    post.postId = obj.postId;
    post.postBody = obj.postBody;
    return post;
}
function convert(array) {
    var map = {};
    for (var i = 0; i < array.length; i++) {
        var currentObject = array[i];


        if (!map[currentObject.userId]) {
            obj = {}
            obj.userId = currentObject.userId;
            obj.userEmail = currentObject.userEmail;
            obj.posts = [];

            map[obj.userId] = obj;

        }
        obj.posts.push(createPost(currentObject));
    }
    var keys = Object.keys(map);
    return keys.map(function (v) { return map[v]; });
}
var r = convert(arry)
console.log(r);

Antwoord #2

Je kunt Array.prototype.reduce() gebruiken om het doel te bereiken.

var source =
    [
    {
        userId: 1,
        userEmail: '[email ',
        postId: 1,
        postBody: 'User 1\'s first post',
    },
    {
        userId: 1,
        userEmail: '[email ',
        postId: 2,
        postBody: 'User 1\'s second post',
    },
    {
        userId: 2,
        userEmail: '[email ',
        postId: 3,
        postBody: 'User 2\'s first post',
    },


]


var grouped = source.reduce(function(v,k){
    if (!v[k.userId]) {
        v[k.userId]={};
    }
    var group = v[k.userId];
    group.userId=k.userId;
    group.userEmail=k.userEmail;
    if(!group.posts){
        group.posts=[];
    }
    group.posts.push({postId: k.postId,
        postBody:k.postBody})
    return v;
},{})

var dataArray = [];
for(var o in grouped) {
    if (grouped.hasOwnProperty(o)) {
        dataArray.push(grouped[o]);
    }
}

console.log(JSON.stringify(dataArray,null, 2));