如何在Angular JS中合并这两个对象?

时间:2016-05-24 16:39:45

标签: javascript arrays angularjs object array-merge

我需要帮助合并AngularJS中的两个对象:)

我正在使用trakt.tv API(http://docs.trakt.apiary.io/)来提取历史数据。 这将返回用户观看的电影和剧集列表(请参阅:http://docs.trakt.apiary.io/#reference/sync/get-history

正如您所看到的,它不包含特定电影或剧集的用户评分。 但有一种方法可以获得电影和电视节目的所有用户评级等。 (见http://docs.trakt.apiary.io/#reference/sync/get-ratings

所以我想要做的是将用户电影/剧集评分与历史列表中的电影/剧集相匹配,但我无法理解它应该如何完成。

示例“历史”对象:

[
  {
    "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
      }
    }
  }
]

示例“评级”对象:

[
  {
    "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

欢迎所有帮助! :)

由于

1 个答案:

答案 0 :(得分:1)

在op的评论之后,ES6不是一个选项,我创建了一个与find辅助方法相当的ES5,以模仿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];
  }
}

fiddle

在我的评论中,我说你可以使用ES5的array.some然而我撒了谎。如果单个匹配符合您的条件(适用于过滤器),some将返回true,但我们需要实际对象。

幸运的是,ES6再次使用find为我们节省了费用; (您可以在ES5中使用过滤器,但这会为我们提供一个数组)

因此,这样的事情应该很容易。

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也可能不会出现。您可以通过像babel这样的东西来运行ES6,转换成ES5,或者使用各种for loops来完成上述所有操作。

Fiddle