【问题标题】:Angular Nested array filtering whole object角度嵌套数组过滤整个对象
【发布时间】:2017-02-02 00:23:24
【问题描述】:

我在controller.js 和gallery.html 上有如下代码

	.controller ('VideoGalleryController', ['$scope', 'videogalleryFactory', function($scope, videogalleryFactory){				
	    //Values of genre searchbox
		$scope.genreOptions = [
	        'Action',
	        'Adventure',
	        'Comedy',
	        'Crime',
	        'Drama',
	        'Historical',
	        'Horror',
	        'Mistery',
	        'Musical',
	        'Romance',
	        'Science Fiction',
	        'Thriller',
	        'Western'
	        ];
		
		//Get dishes from db_movies.json
		videogalleryFactory.getMovies().query(
                function(response) {
                    $scope.movies = response;
                    //Displays nested genres
                    angular.forEach($scope.movies, function(item){
                    	console.log(item.genre);
                    })
                },
                function(response) {
                    $scope.message = "Error: "+response.status + " " + response.statusText;
                });					
	}])
	<div class="row row-content-cards">
		<div class="col-xs-12 col-sm-9">
			<!-- Title filter --> 
			<div class="form-group">
				<label class="col-sm-3 control-label label-title" for="search">Search movie:</label>
				<div class="col-sm-9">
					<input type="text" class="form-control" placeholder="Search movie" ng-model="moviesfilter.title">
				</div>
			</div>
			<!-- Genre filter -->
			<div class="form-group">
				<label for="genre" class="col-sm-3 control-label">Search genre</label> 			                       
				<div class="col-sm-9">
					<select class="form-control"
							multiple 
							chosen 			
							id="genre"
							name="genre" 							
							data-placeholder="Search genres"
							no-results-text="'Could not find that genre'"
							ng-model="???" 
							ng-options="s for s in genreOptions">
							<option value=""></option>
					</select>				
				</div>			
			</div>
		</div>
	</div>
   
	<div class="container-fluid cards-row">
		<div calss="hover-effect">
			<div class="col-sm-6 col-md-4" ng-repeat="movie in movies | filter:moviesfilter as filtText">
				<div class="hover-div">
		    		<div class="thumbnail">
		      			<img ng-src={{movie.cover}} alt="{{movie.alt}}" >
		      			<div class="caption">
		        			<h3>{{movie.title}}</h3>
		        			<span class="badge-space badge" ng-repeat="genre in movie.genre | filter:genre"><strong>{{genre}} </strong></span>
		        			<div class="titlewraptext">
		        				{{movie.plot}}
		        			</div>
		        			<p><a href="#" class="btn btn-primary" role="button">Details</a></p>
		      			</div>
		    		</div>
		  		</div>
			</div>
		</div>	
	</div>
	<p ng-if="filtText.length === 0">
	      <strong>No results found...</strong>
    <p>
</div>

我想在Filter by genre screenshot 上选择一个值,然后过滤整个电影。在此示例中,仅应显示“La momia”和“Gladiator”。

json文件结构如下:

{
  "movies": [
    {
      "title": "La momia",
      "releasedate": "1998-12-31T23:00:00.000Z",
      "length": 125,
      "genre": [
        "Adventure"
      ],
      "plot": "Durante una batalla en Egipto, el legionario Rick O'Connell y un compañero descubren las ruinas de Hamunaptra, la ciudad de los muertos. Algún tiempo después vuelven al mismo lugar con una egiptóloga y su hermano. Allí coinciden con un grupo de estadounidenses, deseosos de correr aventuras, que acabarán provocando la resurrección de la momia de un diabólico sacerdote egipcio que intenta desesperadamente recuperar a su amada.",
      "cast": "Brendan Fraser, Rachel Weisz, John Hannah, Arnold Vosloo, Jonathan Hyde, Oded Fehr, Kevin J. O'Connor, Stephen Dunham, Aharon Ipalé, Tuc Watkins, Omid Djalili, Erick Avari, Carl Chase, Corey Johnson, Bernard Fox, Patricia Velasquez, Ray Donn",
      "cover": "img/film_covers/lamomia.png",
      "downloaddate": "2000-02-04T23:00:00.000Z",
      "alt": "La momia",
      "id": 1
    },
    {
      "title": "Los juegos del hambre",
      "releasedate": "2011-12-31T23:00:00.000Z",
      "length": 143,
      "plot": "Lo que en el pasado fueron los Estados Unidos, ahora es una nación llamada Panem; un imponente Capitolio ejerce un control riguroso sobre los 12 distritos que lo rodean y que están aislados entre sí. Cada distrito se ve obligado a enviar anualmente un chico y una chica entre los doce y los dieciocho años para que participen en los Hunger Games, unos juegos que son transmitidos en directo por la televisión. Se trata de una lucha a muerte, en la que sólo puede haber un superviviente. Katniss Everdeen, una joven de dieciséis años, decide sustituir a su hermana en los juegos; pero para ella, que ya ha visto la muerte de cerca, la lucha por la supervivencia es su segunda naturaleza.",
      "cover": "img/film_covers/losjuegosdelhambre.jpg",
      "cast": "Jennifer Lawrence, Josh Hutcherson, Elizabeth Banks, Woody Harrelson, Donald Sutherland, Stanley Tucci, Liam Hemsworth, Toby Jones, Lenny Kravitz, Wes Bentley, Paula Malcomson, Isabelle Fuhrman, Sandra Ellis Lafferty, Paula Malcomson, Kimiko Gelman, Nelson Ascencio, Brooke Bundy, Amandla Stenberg, Dayo Okeniyi, Leven Rambin, Jack Quaid, Latarsha Rose, Alexander Ludwig, Jacqueline Emerson",
      "downloaddate": null,
      "alt": "Los juegos del hambre",
      "genre": [
        "Action",
        "Drama",
        "Science Fiction"
      ],
      "id": 2
    },
    {
      "title": "Gladiator",
      "releasedate": "2000-04-30T22:00:00.000Z",
      "length": 155,
      "plot": "En el año 180, el Imperio Romano domina todo el mundo conocido. Tras una gran victoria sobre los bárbaros del norte, el anciano emperador Marco Aurelio (Richard Harris) decide transferir el poder a Máximo (Russell Crowe), bravo general de sus ejércitos y hombre de inquebrantable lealtad al imperio. Pero su hijo Cómodo (Joaquin Phoenix), que aspiraba al trono, no lo acepta y trata de asesinar a Máximo.",
      "cover": "img/film_covers/gladiator.jpg",
      "cast": "Russell Crowe, Joaquin Phoenix, Connie Nielsen, Oliver Reed, Richard Harris, Ralf Moeller, Derek Jacobi, Djimon Hounsou, David Schofield, John Shrapnel, Spencer Treat Clark, Tomas Arana, David Hemmings, Tommy Flanagan, Sven-Ole Thorsen, Tony Curran, Giorgio Cantarini, Omid Djalili, Giannina Facio, Michael Sheen",
      "downloaddate": null,
      "alt": "Gladiator",
      "genre": [
        "Action",
        "Adventure",
        "Drama",
        "Historical"
      ],
      "id": 3
    }
  ],
  "series": []
}

【问题讨论】:

  • 所有 angular.forEach 要做的就是迭代所有对象并显示类型。好奇,你是什么 a) 使用 angular.foreach 而不是 Array.forEach 和 b) 你为什么不使用 Array.filter 而不是迭代它?
  • 那个 angular.forEach 仅用于调试目的。它只是在控制台中显示每部电影的类型
  • 对,但是从您的问题来看,您要过滤吗?现在还早,我的咖啡还没喝完,但我没有看到任何过滤逻辑。
  • 这很难解释。 “gallery.html”上的选择框显示不同类型的列表。我想要的是,一旦选择了一种类型,就可以过滤和显示具有该类型的整张卡片(电影)。在屏幕截图中,应该只显示 2 张卡片。什么都没有开发,因为我所有的尝试都没有成功,所以我不知道该怎么做。
  • 我将发布一个示例,说明如何根据流派过滤 JSON,以返回仅包含所需项目的数组。然后,您可以使用该数组绑定到 ng 循环,或者以任何方式显示它。

标签: javascript angularjs angularjs-ng-repeat angular-filters


【解决方案1】:

这样就可以了。

let target_genre = 'Adventure'; // what your user selected
let movies = obj.movies; // your movies array from your JSON

// Find out if a movie's genres contains the target genre
// If so, return it to the new array.
let movies_filtered = movies.filter ( x => { 
  return x.genre.indexOf ( target_genre ) >= 0 } );

console.log ( movies_filtered ); // two movies

编辑:由于实际使用的是一系列类型,因此您可以在此处测试“任何类型匹配”或“所有类型匹配”。请注意,现在的假设是,如果它可以是一个流派数组,它应该总是一个流派数组,即使它是一个长的,否则你必须写“如果它是一个数组就这样做,如果不是这样做,”代码。如果它总是一个数组,即使是一个长数组,你也总是以“它是一个数组”的方式来做。

let target_genres = [ 'Adventure', 'Drama', 'Historical' ];
let movies = obj.movies; // your movies array

// Returns if any genre matches
let movies_filtered = movies.filter ( x => { 
  return target_genres.filter ( y => {
    return x.genre.indexOf ( y ) >= 0;
  }).length; // if length is 0, that's "false", anything else is "true".
});

// Returns if all genres match
let movies_filtered = movies.filter ( x => { 
  let originalLength = target_genres.length;
  return target_genres.filter ( y => {
    return x.genre.indexOf ( y ) >= 0;
  }).length === originalLength; // filtered array length must match original length
});

【讨论】:

  • 成功了!!如您所说,它返回带有 2 部电影的数组!现在我必须让它适应我的需要!非常感谢。
  • 是的,当您看到答案时,这些算法看起来多么简单,这不是很烦人。我学到的关于 algs 的一件事是,如果您需要多于几行代码来测试基本案例,那么您可能走错了方向。然而,map/filter/reduce(fold) 以及现在的 Sets、union/diff/intersection 非常简单,对于任何 JS 开发人员来说都是绝对需要阅读的。
  • 一个小问题,如果我想在流派上传递 2 个参数?谁会起作用?我试过:target_genre = ['Adventure','Historical];但它返回空数组
  • 是的,这是行不通的,因为 target 应该是一个字符串,而不是一个数组(你不能像那样交换东西)。但是,如果您循环该目标类型数组并在该循环中运行上述代码,则可以在不更改代码的情况下执行此操作。否则,您将在过滤器函数中循环目标类型,如果其中任何一个 >= 0,则返回它。
  • 用“找到任何类型,找到所有类型”更新答案。请注意,如果您可能会提交一个流派数组,那么您应该始终提交一个数组,即使它是一个长度 = 1 的数组(这样您就不必编写任何代码来表示,“如果不是数组,就这样做,如果是,就那样做”。它总是一个数组,所以你总是这样做)。
【解决方案2】:

您可以将此解决方案与 es6 一起使用 :)

const filteredMoviesByGenreType = (data, genreType) => {
   // access to object with key "movies" in data via spread operator and dot notation and filtering by genreType
   return [...data.movies]
     .filter(movie => movie["genre"]
     .includes(genreType));
 }

data 是来自服务器的整个 json 数据。

例如仅适用于戏剧类型的输出:

filteredMoviesByGenreType(data, "Drama");

[[object Object] {
  alt: "Los juegos del hambre",
  cast: "Jennifer Lawrence, Josh Hutcherson, Elizabeth Banks, Woody Harrelson, Donald Sutherland, Stanley Tucci, Liam Hemsworth, Toby Jones, Lenny Kravitz, Wes Bentley, Paula Malcomson, Isabelle Fuhrman, Sandra Ellis Lafferty, Paula Malcomson, Kimiko Gelman, Nelson Ascencio, Brooke Bundy, Amandla Stenberg, Dayo Okeniyi, Leven Rambin, Jack Quaid, Latarsha Rose, Alexander Ludwig, Jacqueline Emerson",
  cover: "img/film_covers/losjuegosdelhambre.jpg",
  downloaddate: null,
  genre: ["Action", "Drama", "Science Fiction"],
  id: 2,
  length: 143,
  plot: "Lo que en el pasado fueron los Estados Unidos, ahora es una nación llamada Panem; un imponente Capitolio ejerce un control riguroso sobre los 12 distritos que lo rodean y que están aislados entre sí. Cada distrito se ve obligado a enviar anualmente un chico y una chica entre los doce y los dieciocho años para que participen en los Hunger Games, unos juegos que son transmitidos en directo por la televisión. Se trata de una lucha a muerte, en la que sólo puede haber un superviviente. Katniss Everdeen, una joven de dieciséis años, decide sustituir a su hermana en los juegos; pero para ella, que ya ha visto la muerte de cerca, la lucha por la supervivencia es su segunda naturaleza.",
  releasedate: "2011-12-31T23:00:00.000Z",
  title: "Los juegos del hambre"
}, [object Object] {
  alt: "Gladiator",
  cast: "Russell Crowe, Joaquin Phoenix, Connie Nielsen, Oliver Reed, Richard Harris, Ralf Moeller, Derek Jacobi, Djimon Hounsou, David Schofield, John Shrapnel, Spencer Treat Clark, Tomas Arana, David Hemmings, Tommy Flanagan, Sven-Ole Thorsen, Tony Curran, Giorgio Cantarini, Omid Djalili, Giannina Facio, Michael Sheen",
  cover: "img/film_covers/gladiator.jpg",
  downloaddate: null,
  genre: ["Action", "Adventure", "Drama", "Historical"],
  id: 3,
  length: 155,
  plot: "En el año 180, el Imperio Romano domina todo el mundo conocido. Tras una gran victoria sobre los bárbaros del norte, el anciano emperador Marco Aurelio (Richard Harris) decide transferir el poder a Máximo (Russell Crowe), bravo general de sus ejércitos y hombre de inquebrantable lealtad al imperio. Pero su hijo Cómodo (Joaquin Phoenix), que aspiraba al trono, no lo acepta y trata de asesinar a Máximo.",
  releasedate: "2000-04-30T22:00:00.000Z",
  title: "Gladiator"
}]

【讨论】:

    猜你喜欢
    • 2021-01-27
    • 1970-01-01
    • 1970-01-01
    • 2019-01-29
    • 1970-01-01
    • 1970-01-01
    • 2020-03-11
    • 1970-01-01
    • 2020-03-08
    相关资源
    最近更新 更多