【问题标题】:Javascript: How to insert dynamic keys into map/objects?Javascript:如何将动态键插入地图/对象?
【发布时间】:2016-11-12 10:03:14
【问题描述】:

我是 JS 初学者,正在做基础教程。我正在尝试执行 zip 函数以返回 {videoID: bookmarkID} 列表。举个例子:

var videos = [
        {
            "id": 70111470,
            "title": "Die Hard"
        },
        {
            "id": 654356453,
            "title": "Bad Boys"
        },
        {
            "id": 65432445,
            "title": "The Chamber"
        }
    ],
    bookmarks = [
        {id: 470, time: 23432},
        {id: 453, time: 234324},
        {id: 445, time: 987834}
    ];
}

这不起作用(我得到了意外的令牌'.'):

return Array.zip(videos,bookmarks, function(v, b){
  return {v.id: b.id};
});

这样做,但返回一个包含 {'v': bookmarkID} 的列表:

return Array.zip(videos,bookmarks, function(v, b){
  return {v: b.id};
});

如何让视频 ID 成为值 bookmarkID 的键?另外,这些技术上是地图还是物体?谢谢。

【问题讨论】:

  • 这两个id是怎么映射在一起的?最后三位?
  • 只是简单地按照列表的顺序,所以第一个视频 id 和第一个书签 id 等等。

标签: javascript object dictionary maps


【解决方案1】:

试试:

return Array.zip(videos,bookmarks, function(v, b){
  return {[v.id]: b.id};
});

【讨论】:

  • 这就是我要找的!你能解释一下为什么这行得通或为什么我的行不通吗? zip 实现只是遍历两个数组并在左右列表中的每个元素上运行函数,那么为什么我不能在两者中传递 ID?
  • 我不知道这个,太好了!
  • 这其实是新的 ES6 自带的一个新的 JS 特性,它的名字叫Computed Property Names
【解决方案2】:

您可以映射一个并使用相同的索引获取另一个的元素。

var videos = [{ "id": 70111470, "title": "Die Hard" }, { "id": 654356453, "title": "Bad Boys" }, { "id": 65432445, "title": "The Chamber" }],
    bookmarks = [{ id: 470, time: 23432 }, { id: 453, time: 234324 }, { id: 445, time: 987834 }],
    zipped = videos.map(function (v, i) {
        var o = {};
        o[v.id] =  bookmarks[i].id;
        return o;
    });

console.log(zipped);
.as-console-wrapper { max-height: 100% !important; top: 0; }

ES6

var videos = [{ "id": 70111470, "title": "Die Hard" }, { "id": 654356453, "title": "Bad Boys" }, { "id": 65432445, "title": "The Chamber" }],
    bookmarks = [{ id: 470, time: 23432 }, { id: 453, time: 234324 }, { id: 445, time: 987834 }],
    zipped = videos.map((v, i) => ({ [v.id]: bookmarks[i].id }));

console.log(zipped);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

  • 返回 { videoID: v.id, bookmarkID: bookmarks[i].id } 我正在寻找 {v.id: bookmark.id}
【解决方案3】:

您的第一次尝试不起作用,因为您使用的对象的密钥不正确。使用对象字面量定义对象时,键必须是数字或字符串字面量。

另一方面,您可以使用类似数组的表示法在对象中创建该键来解决该问题。在 JS 中有两种方法可以访问对象中键的值:使用点表示法或类似数组的表示法。类似数组的表示法允许您访问直到运行时才确定的对象的键(作为变量的键)。例如:

var obj = {};
for(var i = 0; i < 3; i++)
  obj[i] = i + 1;
console.log(obj);

如果您有兴趣,两者在性能方面并没有太大差异。

回到你的问题。 Zip 是一个函数,用函数式程序员的话来说,它接受一对列表并创建一个对列表。从我的观点(以及我认为的功能观点)来看,以不同的方式处理它可能更明智。

例如(作为一个快速的想法),您可以创建一个执行 zip(典型 zip)的函数,并将结果应用于另一个选择您感兴趣的值的函数:

var videos = [{
    "id": 70111470,
    "title": "Die Hard"
  }, {
    "id": 654356453,
    "title": "Bad Boys"
  }, {
    "id": 65432445,
    "title": "The Chamber"
  }],
  bookmarks = [{
    id: 470,
    time: 23432
  }, {
    id: 453,
    time: 234324
  }, {
    id: 445,
    time: 987834
  }];

// Assuming same size.
function zip(list1, list2) {
  return list1.length ?
    [[list1[0], list2[0]]].concat(zip(list1.slice(1), list2.slice(1))) : [];
}

function makeObj(list) {
  var obj = {};
  obj[list[0].id] = list[1].id;
  return obj;
}

console.log(zip(videos, bookmarks).map(makeObj));

我使用递归制作了一个简单的 zip(有优化的方法,也可以考虑到列表可以有不同的大小),但我认为它可以帮助您掌握这个想法。

希望对你有帮助

【讨论】:

  • 感谢您的详尽解释;真的很有帮助!
猜你喜欢
  • 2022-06-11
  • 1970-01-01
  • 1970-01-01
  • 2016-03-18
  • 2011-04-30
  • 2014-05-20
  • 2021-07-24
  • 1970-01-01
  • 2017-06-26
相关资源
最近更新 更多