如何在 Angular JS 中合并这两个对象?
How to merge these two objects in Angular JS?
我需要帮助合并 AngularJS 中的两个对象 :)
我正在使用 trakt.tv API (http://docs.trakt.apiary.io/) 来提取历史数据。
此 returns 用户观看过的电影和剧集列表(参见:http://docs.trakt.apiary.io/#reference/sync/get-history)
如您所见,它不保存用户对特定电影或剧集的评分。
但是有一种方法可以获得所有用户对电影和电视节目等的评分。
(参见 http://docs.trakt.apiary.io/#reference/sync/get-ratings)
所以我想做的是将用户 movie/episode 的评分与历史列表中的 movie/episode 相匹配,但我不知道应该怎么做。
示例 "History" 对象:
[
{
"id": 2008588422,
"watched_at": "2016-05-17T10:36:12.000Z",
"action": "watch",
"type": "movie",
"movie": {
"title": "Batman v Superman: Dawn of Justice",
"year": 2016,
"ids": {
"trakt": 129583,
"slug": "batman-v-superman-dawn-of-justice-2016",
"imdb": "tt2975590",
"tmdb": 209112
}
}
},
{
"id": 1995814508,
"watched_at": "2016-05-09T22:39:47.000Z",
"action": "checkin",
"type": "movie",
"movie": {
"title": "Dirty Grandpa",
"year": 2016,
"ids": {
"trakt": 188691,
"slug": "dirty-grandpa-2016",
"imdb": "tt1860213",
"tmdb": 291870
}
}
},
{
"id": 2005359787,
"watched_at": "2016-05-09T01:00:00.000Z",
"action": "watch",
"type": "episode",
"episode": {
"season": 6,
"number": 3,
"title": "Oathbreaker",
"ids": {
"trakt": 1989021,
"tvdb": 5579003,
"imdb": "tt4131606",
"tmdb": 1186952,
"tvrage": 1065908650
}
},
"show": {
"title": "Game of Thrones",
"year": 2011,
"ids": {
"trakt": 1390,
"slug": "game-of-thrones",
"tvdb": 121361,
"imdb": "tt0944947",
"tmdb": 1399,
"tvrage": 24493
}
}
}
]
示例 "Ratings" 对象:
[
{
"rated_at": "2016-05-17T10:36:28.000Z",
"rating": 7,
"type": "movie",
"movie": {
"title": "Batman v Superman: Dawn of Justice",
"year": 2016,
"ids": {
"trakt": 129583,
"slug": "batman-v-superman-dawn-of-justice-2016",
"imdb": "tt2975590",
"tmdb": 209112
}
}
},
{
"rated_at": "2016-04-05T15:55:36.000Z",
"rating": 8,
"type": "movie",
"movie": {
"title": "You Don't Mess With the Zohan",
"year": 2008,
"ids": {
"trakt": 5835,
"slug": "you-don-t-mess-with-the-zohan-2008",
"imdb": "tt0960144",
"tmdb": 10661
}
}
},
{
"rated_at": "2016-05-24T16:19:54.000Z",
"rating": 8,
"type": "episode",
"episode": {
"season": 6,
"number": 3,
"title": "Oathbreaker",
"ids": {
"trakt": 1989021,
"tvdb": 5579003,
"imdb": "tt4131606",
"tmdb": 1186952,
"tvrage": 1065908650
}
},
"show": {
"title": "Game of Thrones",
"year": 2011,
"ids": {
"trakt": 1390,
"slug": "game-of-thrones",
"tvdb": 121361,
"imdb": "tt0944947",
"tmdb": 1399,
"tvrage": 24493
}
}
}
]
想要的结果:
[
{
"id": 2008588422,
"rated_at": "2016-05-17T10:36:28.000Z",
"rating": 7,
"watched_at": "2016-05-17T10:36:12.000Z",
"action": "watch",
"type": "movie",
"movie": {
"title": "Batman v Superman: Dawn of Justice",
"year": 2016,
"ids": {
"trakt": 129583,
"slug": "batman-v-superman-dawn-of-justice-2016",
"imdb": "tt2975590",
"tmdb": 209112
}
}
},
{
"id": 1995814508,
"watched_at": "2016-05-09T22:39:47.000Z",
"action": "checkin",
"type": "movie",
"movie": {
"title": "Dirty Grandpa",
"year": 2016,
"ids": {
"trakt": 188691,
"slug": "dirty-grandpa-2016",
"imdb": "tt1860213",
"tmdb": 291870
}
}
},
{
"id": 2005359787,
"rated_at": "2016-05-24T16:19:54.000Z",
"rating": 8,
"watched_at": "2016-05-09T01:00:00.000Z",
"action": "watch",
"type": "episode",
"episode": {
"season": 6,
"number": 3,
"title": "Oathbreaker",
"ids": {
"trakt": 1989021,
"tvdb": 5579003,
"imdb": "tt4131606",
"tmdb": 1186952,
"tvrage": 1065908650
}
},
"show": {
"title": "Game of Thrones",
"year": 2011,
"ids": {
"trakt": 1390,
"slug": "game-of-thrones",
"tvdb": 121361,
"imdb": "tt0944947",
"tmdb": 1399,
"tvrage": 24493
}
}
}
]
基本上评分数据应该添加到历史对象中的相应电影和剧集中。
angular.merge 或 .extend 没有给出想要的结果,这些看起来是非常基本的文档 (https://docs.angularjs.org/api/ng/function/angular.merge)
欢迎大家帮忙! :)
谢谢
在 op 的评论(其中 ES6 不是一个选项)之后,我创建了一个 ES5 等效项,其中包含一个 find
辅助方法来模仿 ES6 的查找。
var merged = history.map(function (h) {
var x = find(ratings, function (r) {
return comparator(h, r);
});
return x ? angular.merge(h, x) : h;
});
/*
Utility fn to get array.find style behaviour
*/
function find(arr, fn) {
if (!Array.isArray(arr))
return undefined;
for(var i = 0; i < arr.length; i++){
if (fn(arr[i]))
return arr[i];
}
}
在我的评论中我说过你可以使用 ES5 的 array.some
但是我撒了谎。 some
将 return 如果单个匹配项符合您的条件(适用于过滤器),则为真,但我们需要实际对象。
幸运的是 ES6 用 find 再次拯救了我们; (你可以在 ES5 中使用 filter 但这给了我们一个数组)
所以像这样的事情应该很容易。
let merged = history.map(h => {
let x = ratings.find(r => comparator(r, h));
return x ? angular.merge(h, x) : h;
});
function comparator(review, history) {
return review[review.type].ids.trakt === history[history.type].ids.trakt;
}
一如既往,这是 ES6,因此 IE 也可能不会出现。你可以 运行 你的 ES6 通过 babel 之类的东西转换成 ES5,或者用各种 for loops
.
做以上所有事情
我需要帮助合并 AngularJS 中的两个对象 :)
我正在使用 trakt.tv API (http://docs.trakt.apiary.io/) 来提取历史数据。 此 returns 用户观看过的电影和剧集列表(参见:http://docs.trakt.apiary.io/#reference/sync/get-history)
如您所见,它不保存用户对特定电影或剧集的评分。 但是有一种方法可以获得所有用户对电影和电视节目等的评分。 (参见 http://docs.trakt.apiary.io/#reference/sync/get-ratings)
所以我想做的是将用户 movie/episode 的评分与历史列表中的 movie/episode 相匹配,但我不知道应该怎么做。
示例 "History" 对象:
[
{
"id": 2008588422,
"watched_at": "2016-05-17T10:36:12.000Z",
"action": "watch",
"type": "movie",
"movie": {
"title": "Batman v Superman: Dawn of Justice",
"year": 2016,
"ids": {
"trakt": 129583,
"slug": "batman-v-superman-dawn-of-justice-2016",
"imdb": "tt2975590",
"tmdb": 209112
}
}
},
{
"id": 1995814508,
"watched_at": "2016-05-09T22:39:47.000Z",
"action": "checkin",
"type": "movie",
"movie": {
"title": "Dirty Grandpa",
"year": 2016,
"ids": {
"trakt": 188691,
"slug": "dirty-grandpa-2016",
"imdb": "tt1860213",
"tmdb": 291870
}
}
},
{
"id": 2005359787,
"watched_at": "2016-05-09T01:00:00.000Z",
"action": "watch",
"type": "episode",
"episode": {
"season": 6,
"number": 3,
"title": "Oathbreaker",
"ids": {
"trakt": 1989021,
"tvdb": 5579003,
"imdb": "tt4131606",
"tmdb": 1186952,
"tvrage": 1065908650
}
},
"show": {
"title": "Game of Thrones",
"year": 2011,
"ids": {
"trakt": 1390,
"slug": "game-of-thrones",
"tvdb": 121361,
"imdb": "tt0944947",
"tmdb": 1399,
"tvrage": 24493
}
}
}
]
示例 "Ratings" 对象:
[
{
"rated_at": "2016-05-17T10:36:28.000Z",
"rating": 7,
"type": "movie",
"movie": {
"title": "Batman v Superman: Dawn of Justice",
"year": 2016,
"ids": {
"trakt": 129583,
"slug": "batman-v-superman-dawn-of-justice-2016",
"imdb": "tt2975590",
"tmdb": 209112
}
}
},
{
"rated_at": "2016-04-05T15:55:36.000Z",
"rating": 8,
"type": "movie",
"movie": {
"title": "You Don't Mess With the Zohan",
"year": 2008,
"ids": {
"trakt": 5835,
"slug": "you-don-t-mess-with-the-zohan-2008",
"imdb": "tt0960144",
"tmdb": 10661
}
}
},
{
"rated_at": "2016-05-24T16:19:54.000Z",
"rating": 8,
"type": "episode",
"episode": {
"season": 6,
"number": 3,
"title": "Oathbreaker",
"ids": {
"trakt": 1989021,
"tvdb": 5579003,
"imdb": "tt4131606",
"tmdb": 1186952,
"tvrage": 1065908650
}
},
"show": {
"title": "Game of Thrones",
"year": 2011,
"ids": {
"trakt": 1390,
"slug": "game-of-thrones",
"tvdb": 121361,
"imdb": "tt0944947",
"tmdb": 1399,
"tvrage": 24493
}
}
}
]
想要的结果:
[
{
"id": 2008588422,
"rated_at": "2016-05-17T10:36:28.000Z",
"rating": 7,
"watched_at": "2016-05-17T10:36:12.000Z",
"action": "watch",
"type": "movie",
"movie": {
"title": "Batman v Superman: Dawn of Justice",
"year": 2016,
"ids": {
"trakt": 129583,
"slug": "batman-v-superman-dawn-of-justice-2016",
"imdb": "tt2975590",
"tmdb": 209112
}
}
},
{
"id": 1995814508,
"watched_at": "2016-05-09T22:39:47.000Z",
"action": "checkin",
"type": "movie",
"movie": {
"title": "Dirty Grandpa",
"year": 2016,
"ids": {
"trakt": 188691,
"slug": "dirty-grandpa-2016",
"imdb": "tt1860213",
"tmdb": 291870
}
}
},
{
"id": 2005359787,
"rated_at": "2016-05-24T16:19:54.000Z",
"rating": 8,
"watched_at": "2016-05-09T01:00:00.000Z",
"action": "watch",
"type": "episode",
"episode": {
"season": 6,
"number": 3,
"title": "Oathbreaker",
"ids": {
"trakt": 1989021,
"tvdb": 5579003,
"imdb": "tt4131606",
"tmdb": 1186952,
"tvrage": 1065908650
}
},
"show": {
"title": "Game of Thrones",
"year": 2011,
"ids": {
"trakt": 1390,
"slug": "game-of-thrones",
"tvdb": 121361,
"imdb": "tt0944947",
"tmdb": 1399,
"tvrage": 24493
}
}
}
]
基本上评分数据应该添加到历史对象中的相应电影和剧集中。
angular.merge 或 .extend 没有给出想要的结果,这些看起来是非常基本的文档 (https://docs.angularjs.org/api/ng/function/angular.merge)
欢迎大家帮忙! :)
谢谢
在 op 的评论(其中 ES6 不是一个选项)之后,我创建了一个 ES5 等效项,其中包含一个 find
辅助方法来模仿 ES6 的查找。
var merged = history.map(function (h) {
var x = find(ratings, function (r) {
return comparator(h, r);
});
return x ? angular.merge(h, x) : h;
});
/*
Utility fn to get array.find style behaviour
*/
function find(arr, fn) {
if (!Array.isArray(arr))
return undefined;
for(var i = 0; i < arr.length; i++){
if (fn(arr[i]))
return arr[i];
}
}
在我的评论中我说过你可以使用 ES5 的 array.some
但是我撒了谎。 some
将 return 如果单个匹配项符合您的条件(适用于过滤器),则为真,但我们需要实际对象。
幸运的是 ES6 用 find 再次拯救了我们; (你可以在 ES5 中使用 filter 但这给了我们一个数组)
所以像这样的事情应该很容易。
let merged = history.map(h => {
let x = ratings.find(r => comparator(r, h));
return x ? angular.merge(h, x) : h;
});
function comparator(review, history) {
return review[review.type].ids.trakt === history[history.type].ids.trakt;
}
一如既往,这是 ES6,因此 IE 也可能不会出现。你可以 运行 你的 ES6 通过 babel 之类的东西转换成 ES5,或者用各种 for loops
.