【问题标题】:Javascript library to collect objects properties, do batch processing and map results back to objects用于收集对象属性、进行批处理并将结果映射回对象的 Javascript 库
【发布时间】:2018-11-10 19:00:59
【问题描述】:

对于对象数组:

[
    {id: 1, name: "test", tagId: 1},
    {id: 2, name: "test", tagId: 15},
    {id: 3, name: "test", tagId: 5},
]

需要将特定属性列表(tagId)缩减为唯一数组[1,15,5],调用一些批处理方法,例如对实体列表的API进行http请求:

async (ids) => await axios.get('http://apihost/tag', {id: ids})

对于对象的结果数组:

[
    {id: 1, name: "tag1"},
    {id: 15, name: "tag2"},
    {id: 5, name: "tag3"},
]

最后需要通过ID属性将这个对象映射到由result.id => original.tagId匹配的原始对象数组,实际上是对两个数组进行SQL连接来得到这个(如https://github.com/mtraynham/lodash-joins):

[
    {id: 1, name: "test", tagId: 1, tag: {id: 1, name: "tag1"}},
    {id: 2, name: "test", tagId: 15, tag: {id: 15, name: "tag2"}},
    {id: 3, name: "test", tagId: 5, tag: {id: 5, name: "tag3"}},
]

我已经为此编写了一个 PHP 库,其 API 如下:

new BulkMap(source).map(
  'tagId',
  'tag',
  async (ids) => axios.get('http://apihost/tag', {id: ids})
);

但现在我在 JS 中需要这个。是否有任何 Javascript/NodeJS 库可以这样做?它看起来像是微服务中非常常用的模式。

【问题讨论】:

    标签: javascript node.js microservices


    【解决方案1】:

    有趣。这是我的尝试。

    const inits = [
        {id: 1, name: "test", tagId: 1},
        {id: 2, name: "test", tagId: 15},
        {id: 3, name: "test", tagId: 5},
    ];
    
    // Get all ids
    const ids = inits.map(init => init.tagId);
    
    const results = [
        {id: 1, name: "tag1"},
        {id: 15, name: "tag2"},
        {id: 5, name: "tag3"},
    ];
    
    // Add results to object
    const final = inits.map(init => {
        init.tag = results.find(res => res.id === init.tagId);
        return init;
    });
    

    [更新]

    如果您可以确定对象的某些顺序将保持不变,则可以加快速度:

    // Add results to object
    const final = inits.map((init, index) => {
        init.tag = results.[index];
        return init;
    });
    

    为什么 JavaScript 如此性感:(

    【讨论】:

    • 在地图内找到不太好。心源数组可以包含 5k 个对象。需要建立索引。
    • 无论如何,问题不是实现这个,而是在编写自己的之前找到现有的npm包。
    • 我怀疑即使在库中也会有更好的实现
    • 如果您始终确定对象的某些顺序将保持不变,则可以加快速度。然后你只需将第一个分配给第一个,第二个分配给第二个,依此类推..
    • @ClintonYeboah 这将是理想的速度,但如果您不知道顺序是否相同,您可以使用Map 来索引并实现 O(N) 解决方案,而不是O(N^2) 与内部 .find 解决方案一样
    【解决方案2】:

    一种功能性方法。

    const { map, uniq } = require('lodash/fp');
    
    const arr = /* you say you already have this */;
    
    const uniqueIds = uniq(map('tagId', arr));
    const objects = await axios.get('http://apihost/tag', { id: uniqueIds });
    const associated = arr.map(({ id, tagId, name }) => (
      { id, tagId, name, tag: objects.find(o => o.id === tagId) };
    ));
    

    如果你想索引(这可能会避免 O(N^2) 解决方案)

    const byTagId = new Map();
    arr.forEach(o => byTagId.set(o.tagId, o));
    const objects = await axios.get('http://apihost/tag', { id: byTagId.keys() });
    const associated = arr.map(({ id, tagId, name }) => (
      { id, tagId, name, tag: byTagId.get(tagId) }
    ));
    

    【讨论】:

    • 在地图内找到不太好。心源数组可以包含 5k 个对象。需要建立索引,就像 lodash-joins 一样。
    • 感谢您展示如何使用 'tagId' 调用 lodash.map,不知道这个。
    • np。请记住,只有与 lodash/fp 类似。 lodash 正确的参数将颠倒:map(arr, 'tagId')
    • 使用 Map 会更好,因为 uniq+map 可以使用 byTagId.keys() 来获得唯一 ID。
    • @MikhailElfimov 你会发现它的性能更差。它更实用,但您正在创建 N 个更多元素,这将花费 O(N) 时间和 O(N) 空间(尽管是暂时的)。 .forEach 方法在所有方面都将更加高效。
    【解决方案3】:

    我喜欢@RiverTam 解决方案https://stackoverflow.com/a/50629965/962746。唯一要解决的是:源数组中的多个对象可以有相同的tagId,所以我是索引响应对象而不是源对象:

    const lodashUniq = require('lodash.uniq');
    const lodashMap = require('lodash.map');
    
    const source = [
        {id: 1, name: "test", tagId: 1},
        {id: 2, name: "test", tagId: 15},
        {id: 3, name: "test", tagId: 5},
    ];
    
    const uniqueIds = lodashUniq(lodashMap(source, 'tagId'));
    const tags = await axios.get('http://apihost/tag', { id: uniqueIds });
    
    const tagsIndex = new Map(tags.map(tag => [tag.id, tag]));
    const result = source.map(s => (
        {... s, tag: tagsIndex.get(s.tagId)}
    ));
    

    【讨论】:

      猜你喜欢
      • 2017-09-26
      • 1970-01-01
      • 2021-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-16
      • 2012-10-12
      相关资源
      最近更新 更多