【问题标题】:javascript extract objects from nested arrays using a list of idsjavascript 使用 id 列表从嵌套数组中提取对象
【发布时间】:2018-09-04 14:26:26
【问题描述】:

我有一个 id 列表作为参考,我有一个对象,其中包含多个对象,这些对象具有对象数组。

我想在列表中创建一个具有相应 id 的对象数组,这是最快的方式。

const data = {
  "items": {
    "item1": [{
        "id": "id1",
        "info": "info1"
      },
      {
        "id": "id2",
        "info": "info22"
      }
    ],
    "item20": [{
      "id": "id3",
      "info": "info5"
    }],
    "item5": [{
        "id": "id4",
        "info": "info6"
      },
      {
        "id": "id5",
        "info": "info7"
      }
    ]
  }
};

const keep = ['id4', 'id2'];
const results = [];
keep.forEach(function(val) {

  const match = Object.keys(data.items).map(item => {
    return data.items[item].find(obj => obj.id === val)
  });
  results.push(match)
})
console.log('final: ', results)

当前没有返回我想要的。 预期结果将是:

[
    {
      "id": "id2",
      "info": "info22"
    },
    {
        "id": "id4",
        "info": "info6"
    }
]

更新:

如果数据本身是一个对象数组,而我们希望对每个对象都做同样的事情呢?

    const data = [{
      "otherStuff": "otherB",
      "items": {
        "item1": [{
            "id": "id1",
            "info": "info1"
          },
          {
            "id": "id2",
            "info": "info22"
          }
        ],
        "item20": [{
          "id": "id3",
          "info": "info5"
        }],
        "item5": [{
            "id": "id4",
            "info": "info6"
          },
          {
            "id": "id5",
            "info": "info7"
          }
        ]
      }
    }, {
      "otherStuff": "otherA",
      "items": {
        "item1": [{
            "id": "id1",
            "info": "info10000"
          },
          {
            "id": "id2",
            "info": "info220000"
          }
        ],
        "item20": [{
          "id": "id3",
          "info": "info5000"
        }],
        "item5": [{
            "id": "id4",
            "info": "info60000"
          },
          {
            "id": "id5",
            "info": "info7000"
          }
        ]
      }
    }];


const keep = ['id4', 'id2'];
const results = [];

    keep.forEach(function(val) {
      data.forEach(function(entry){
          Object.keys(entry.items).forEach(item => {
            var match = entry.items[item].find(obj => obj.id === val);
            if (match) {
              results.push(match)
            }
          });
      });
    })
    
    console.log(results)

输出应该是:

[
    {
        "otherStuff": "otherB",
        "items": [
                {
                      "id": "id2",
                      "info": "info22"
                },
                {
                    "id": "id4",
                    "info": "info6"
            }
        ]
    },
    {
        "otherStuff": "otherA",
        "items": [
                {
                      "id": "id2",
                      "info": "info220000"
                },
                {
                    "id": "id4",
                    "info": "info60000"
            }
        ]
    }
]

结果不一样。

【问题讨论】:

  • 请访问help center,使用tour查看内容和How to Ask。做一些研究,搜索关于 SO 的相关主题;如果您遇到困难,请发布您的尝试minimal reproducible example,并注明输入和预期输出。
  • @mplungjan 修正了等号中的错字...我需要一个权威的答案来看看最快的方法是什么。
  • 这里不是主题。 Codereview 或许
  • @mplungjan 好的,请关闭它,将其移至 codereview
  • @mplungjan 不! “当前没有返回我想要的” 意味着代码没有按预期工作,这是代码审查的一个密切原因。

标签: javascript arrays multidimensional-array ecmascript-6


【解决方案1】:

如果对保留的 id 使用 Set,则节省了一次 O(n) 遍历:

 const keep = new Set(['id4', 'id2']);

 const result = [];

 for(const items of Object.values(data.items))
   for(const item of items)
     if(keep.has(item.id))
       result.push(item);

【讨论】:

【解决方案2】:

您不需要使用map()。只需在要保留的对象键上使用forEach() 循环并找到匹配的对象,以便将其推送到结果数组中。

const data = {
  "items": {
    "item1": [{
        "id": "id1",
        "info": "info1"
      },
      {
        "id": "id2",
        "info": "info22"
      }
    ],
    "item20": [{
      "id": "id3",
      "info": "info5"
    }],
    "item5": [{
        "id": "id4",
        "info": "info6"
      },
      {
        "id": "id5",
        "info": "info7"
      }
    ]
  }
};

const keep = ['id4', 'id2'];
const results = [];
keep.forEach(function(val) {
  Object.keys(data.items).forEach(item => {
    var match = data.items[item].find(obj => obj.id === val);
    if (match) {
      results.push(match)
    }
  });
})
console.log('final: ', results)

【讨论】:

  • 这是最快的方法吗?过滤/查找/减少/他们不能更快吗?
  • @storis 您在对象内部有一组对象,肯定会有O(n2) 复杂度
  • 我用附件更新了问题,你能看一下吗?在这种情况下,我怎样才能获得类似的结果?
【解决方案3】:

items 是一个对象,item1,item20 是键。所以你可以做Object.values 并对其应用reduce 函数来获得一个由所有对象组成的数组。不迭代keep 数组并从单个数组中过滤掉所需的元素。

const data = {
  "items": {
    "item1": [{
        "id": "id1",
        "info": "info1"
      },
      {
        "id": "id2",
        "info": "info22"
      }
    ],
    "item20": [{
      "id": "id3",
      "info": "info5"
    }],
    "item5": [{
        "id": "id4",
        "info": "info6"
      },
      {
        "id": "id5",
        "info": "info7"
      }
    ]
  }
};



const keep = ['id4', 'id2'];
let getAllObjectValues = Object.values(data.items).reduce(function(acc, curr) {
  curr.forEach((elem) => {
    acc.push(elem)
  })
  return acc;
}, []);

let k = keep.map(function(item) {
  return getAllObjectValues.filter(function(val) {
    return item === val.id
  })[0]

})
console.log(k)

【讨论】:

    【解决方案4】:

    您在 map 函数中使用了赋值运算符而不是等价运算符,请更改为:

    const keep = ['id4', 'id2'];
    const results = [];
    keep.forEach(function(val){
        const match = Object.keys(data.items).map(item => {
            return data.items[item].find(obj => obj.id === val)
        });
        results.push(match)
    })
    console.log('final: ', results)    
    

    【讨论】:

    • 不再是错字类型的问题,但仍然离题
    【解决方案5】:

    使用reducefilter 的组合,您可以迭代每个子数组,检查是否应保留该值。

    const data = {
      "items": {
        "item1": [
          {
            "id": "id1",
            "info": "info1"
          },
          {
            "id": "id2",
            "info": "info22"
          }
        ],
        "item20": [
          {
            "id": "id3",
            "info": "info5"
          }
        ],
        "item5": [
          {
            "id": "id4",
            "info": "info6"
          },
          {
            "id": "id5",
            "info": "info7"
          }
        ]
      }
    };
    
    const keep = ['id4', 'id2'];
    const filter = el => {
      return keep.indexOf(el.id) >= 0;
    };
    
    const reducer = (accumulator, currentValue) => { 
      return accumulator = accumulator.concat(data.items[currentValue].filter(filter));
    };
    
    let results = Object.keys(data.items).reduce(reducer, []);
    
    console.log('final: ', results);

    【讨论】:

      猜你喜欢
      • 2022-01-07
      • 1970-01-01
      • 1970-01-01
      • 2021-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多