Javascript将obj数组与另一个数组映射以获得不同的键值

时间:2018-06-22 18:54:59

标签: javascript arrays object

所以我不确定为什么我会遇到如此困难的时刻,但是我有一个id数组,我试图用它映射到对象数组上以找到相应的id,但是从另一个返回值键。

即: arr=[13, 1, 16]

arrObj= [{
          id: 1,
          name: "cat"
         }, {
          id: 10,
          name: "tiger", 
         }, {
          id: 3,
          name: "dog", 
         }, {
          id: 16,
          name: "bear", 
         }, {
          id: 8,
          name: "fish", 
         }, {
          id: 13,
          name: "goat", 
         }]

,我希望它返回: ["goat", "cat", "bear"]

我有一个嵌套的映射函数,可以执行此操作,但是对于没有相应ID的对象,返回未定义。我可以从返回的数组中过滤出未定义的对象,但是似乎有一种更干净/更有效的方法来实现这一点。

最干净的方法是什么?

5 个答案:

答案 0 :(得分:5)

您可以使用Array#map并使用Array#find搜索相应的对象。然后以name作为返回值。

var arr = [13, 1, 16],
    arrObj = [{ id: 1, name: "cat" }, { id: 10, name: "tiger" }, { id: 3, name: "dog" }, { id: 16, name: "bear" }, { id: 8, name: "fish" }, { id: 13, name: "goat" }],
    result = arr.map(id => arrObj.find(o => o.id === id).name);

console.log(result);

对于大量数据,您可以使用Map并通过映射键值对来构建它,然后映射该映射的结果。

var arr = [13, 1, 16],
    arrObj = [{ id: 1, name: "cat" }, { id: 10, name: "tiger" }, { id: 3, name: "dog" }, { id: 16, name: "bear" }, { id: 8, name: "fish" }, { id: 13, name: "goat" }],
    result = arr.map(
        Map.prototype.get,
        new Map(arrObj.map(({ id, name }) => [id, name]))
    );

console.log(result);

答案 1 :(得分:2)

尝试一下:

var arr=[13, 1, 16];
var arrObj= [{
          id: 1,
          name: "cat"
         }, {
          id: 10,
          name: "tiger", 
         }, {
          id: 3,
          name: "dog", 
         }, {
          id: 16,
          name: "bear", 
         }, {
          id: 8,
          name: "fish", 
         }, {
          id: 13,
          name: "goat", 
         }];

var result = arr.map(id => arrObj.find(x => x.id == id)).map(x => x.name)
console.log(result);
// ["goat", "cat", "bear"]

.map()(来自MDN网络文档):

  

方法使用调用提供的结果创建一个新数组   在调用数组中的每个元素上起作用。

.find()(来自MDN网络文档):

  

方法返回数组中第一个元素   满足提供的测试功能。否则undefined是   返回。

答案 2 :(得分:1)

已经有了很多好的答案,但是我觉得有必要推动更新的语法,因为从长远来看,它的使用范围更大。

const getNamesBasedOnIds = (arr, listOfIds) => {
   return arr.reduce(((sum, element) => 
      [...sum, ...(listOfIds.includes(element.id) ? [element.name] : [])]),
   []);
}

const animals = getNamesBasedOnIds(arrObj, [13,1,16]);

使用Array.filter,然后使用Array.map,需要两次运行Array最大值。

如果{{1}中存在Array.reduce,则可以将elements添加到sum中,然后在运行listOfIds之后,一旦获得结果< / p>

arrObj的运行速度很慢,但是它更多的是用于展示矛操作符的使用情况

以上等同于

[...sum, ...(listOfIds.includes(element.id) ? [element.name] : [])]

最快的方法是使用sum.concat(listOfIds.includes(element.id) ? element.name : [])]

Array.push

答案 3 :(得分:0)

您可以先使用.filter进行过滤,然后使用.map输出所需的属性

此处

var arr = [13, 1, 16],
    arrObj = [{
        id: 1,
        name: "cat"
    }, {
        id: 10,
        name: "tiger",
    }, {
        id: 3,
        name: "dog",
    }, {
        id: 16,
        name: "bear",
    }, {
        id: 8,
        name: "fish",
    }, {
        id: 13,
        name: "goat",
    }];

var res = arrObj.filter(o => arr.indexOf(o.id) >= 0);

console.log(res.map(o => o['name']))

答案 4 :(得分:0)

正确的方法是不嵌套任何循环:

  1. 将对象数组缩减为“ id-values”映射的 idValueMap
  2. 使用 idValueMap 映射“ id”数组 idArr 恒定时间内每个id的对应值。

思考过程

了解最大的问题是数据本身。不要让数据类型或结构不足迫使您使用错误的解决方案/代码。将数据转换为所需的数据,以便可以创建适当的解决方案。

基本上想象一下,如果 objArr 只是一个Map,您可以用来查找id的值...。那么解决方案就很简单了。因此,让我们做到这一点,然后其余的就位。数据数据是我一直说的:)

经验法则如果有帮助,请不要在循环内部运行循环。仅供参考:filter,find,map,indexOf ....都是内部循环,除非绝对必要,否则请勿嵌套它们。

该解决方案是迄今为止性能最高的。这样,您就没有运行 O(n ^ 2)(非常糟糕),而是运行了 O(n)(非常好):

    const idArr = [ 13, 1, 16 ];
    const objArr= [
      {
        id: 1,
        name: "cat"
      }, 
      {
        id: 10,
        name: "tiger", 
      }, 
      {
        id: 3,
        name: "dog", 
      }, 
      {
        id: 16,
        name: "bear", 
      }, 
      {
        id: 8,
        name: "fish", 
      }, 
      {
        id: 13,
        name: "goat", 
      }
    ];
    
    const idValueMap = objArr.reduce((acc, { id, name }) => ({ ...acc, [id]: name }), {});
    let output = idArr.map((id) => idValueMap[id]);
    console.log(output);