2
votes

Mise en correspondance de 2 tableaux par identifiants (utilisateur [identifiant utilisateur en tant que clé] à orders [valeur du tableau ids commandes])

J'ai un tableau d '"utilisateurs" et un tableau de "commandes". Je veux lister tous les order_ids pour chaque user_id.

let userToOrdersArray = users.map( function(user) {

    /*Object.values(orders).reduce((newObj, orderData) => {
        newObj[user.user_id][] = orderData.order_id;
    }, {});*/

    Object.values(orders).filter(function(orderData) {
        return (orderData.user_id === user.user_id); 
    });

});

console.log(userToOrdersArray); 

Quelle est la meilleure pratique (en termes d'efficacité) pour obtenir ce résultat de user_ids (user_id comme clé) aux commandes (valeur du tableau orders ids):

result = {
    111: [ 888, 889 ],
    113: [ 890 ]
};

L'utilisation de l'objet / tableau "user" est un must, car ma variable utilisateur est un liste d'utilisateurs filtrée, et le tableau userToOrder doit récupérer tous les order_ids de certains utilisateurs spécifiques et en créer un nouvel objet.

  • Non pour les boucles, juste une fonctionnalité es6 pure.
  • Essayer d'éviter le .forEach () pour cette pratique sauf si c'est impossible.
  • aucune réponse loadash à moins qu'il n'y ait un exemple "vanilla es6".

Ce furent mes derniers essais, sans aucun succès:

var users = {
    0: {
        user_id: 111,
        user_name: "user111",
        isActive: 0
    },
    1: {
        user_id: 112,
        user_name: "use112",
        isActive: 1
    },
    2: {
        user_id: 113,
        user_name: "use113",
        isActive: 0
    },
    ...
}; 

var orders = {  
    888: {
        order_id: 888, 
        user_id: 111
    }, 
    889: {
        order_id: 889, 
        user_id: 111
    }, 
    890: {
        order_id: 890, 
        user_id: 113
    }
};


2 commentaires

qu'en est-il de l'utilisateur 112 ?


Vous devez savoir que les touches numériques que vous utilisez sont converties en chaînes. Je suggérerais de regarder Map comme il a été spécialement conçu pour ce type de données et ces tâches.


3 Réponses :


1
votes

Vous pouvez utiliser Array Méthode #reduce .

var users = {
  111: {
    user_id: 111,
    user_name: "user111",
    isActive: 0
  },
  112: {
    user_id: 112,
    user_name: "use112",
    isActive: 1
  },
  113: {
    user_id: 113,
    user_name: "use113",
    isActive: 0
  },
};
var orders = {
  888: {
    order_id: 888,
    user_id: 111
  },
  889: {
    order_id: 889,
    user_id: 111
  },
  890: {
    order_id: 890,
    user_id: 113
  }
};


// get all property values
var res = Object.values(orders)
  // iterate over values
  .reduce(function(obj, { user_id, order_id }) { // extract  properios using Destructuring feature
    // check user id present in users array
    if (user_id in users) {
      // define array for ids if not defined previously
      obj[user_id] = obj[user_id] || [];
      // push value to array
      obj[user_id].push(order_id);
    }
    // return object
    return obj;
    // set initial value as object
  }, {})

console.log(res)


5 commentaires

Pas exactement "purement fonctionnel" - votre réducteur fait muter l'accumulateur sur place (`obj [user_id] = obj [user_id] || []; obj [user_id] .push (order_id);`), au lieu de renvoyer une nouvelle valeur (nouvel objet).


Mais il n'est pas filtré à la suite de l'objet utilisateurs.


@mbojko: il ne mute pas, s'il est défini, il se réassigne simplement ou il attribuera un nouveau tableau comme valeur


push () est en train de muter.


@mbojko: oui il veut les regrouper



1
votes

Je suppose ici que pour l'objet users , la clé est toujours égale à la propriété user_id .

const users = {
  111: {
    user_id: 111,
    user_name: "user111",
    isActive: 0
  },
  112: {
    user_id: 112,
    user_name: "use112",
    isActive: 1
  },
  113: {
    user_id: 113,
    user_name: "use113",
    isActive: 0
  },
};

const orders = {
  888: {
    order_id: 888,
    user_id: 111
  },
  889: {
    order_id: 889,
    user_id: 111
  },
  890: {
    order_id: 890,
    user_id: 113
  }
};

const groupOrdersByUsers = (usersArr, ordersArr) => usersArr.map(id => ({[id]: ordersArr.filter(({user_id}) => user_id == id)}));

console.log(groupOrdersByUsers(Object.keys(users), Object.values(orders)));


3 commentaires

vous avez raison monsieur! Je ne sais pas si votre réponse est la plus efficace ou l'autre option mentionnée dans les commentaires de l'article (en utilisant une instruction if).


oh, oups mon mauvais, le bon identifiant d'utilisateur est celui à l'intérieur de la "ligne utilisateur" (user.user_id)


Le plus efficace serait probablement la bonne vieille boucle «for». Pas très joli, cependant. (Pour avoir les deux, il vaudra mieux faire ce côté SQL, c'est ce pour quoi SQL vit ...)



1
votes

Cela devrait faire l'affaire

const users = {
    0: {
        user_id: 111,
        user_name: "user111",
        isActive: 0
    },
    1: {
        user_id: 112,
        user_name: "use112",
        isActive: 1
    },
    2: {
        user_id: 113,
        user_name: "use113",
        isActive: 0
    },
}

  
const orders = {  
  888: {
    order_id: 888, 
    user_id: 111
  }, 
  889: {
    order_id: 889, 
    user_id: 111
  }, 
  890: {
    order_id: 890, 
    user_id: 113
  }
}

const getOrderIdsFromUserId = (user_id, orders) =>
  Object.values(orders).reduce(
    (order_ids, order) => 
      order.user_id===user_id ? [order.order_id,...order_ids] : order_ids,
    []
  )

const f = (users, orders) =>
  Object.values(users).reduce(
    (y, user) => ({
      ...y,
      [user.user_id]: getOrderIdsFromUserId(user.user_id, orders),
    }),
    {},
  )

console.log(f(users, orders))


0 commentaires