How to make ng-repeat filter out duplicate results
我在一个JSON文件上运行一个简单的
我现在的代码是:
1 2 3 | <select ng-model="orderProp"> <option ng-repeat="place in places" value="{{place.category}}">{{place.category}}</option> </select> |
输出是100个不同的选项,大部分是重复的。如何使用Angular检查EDOCX1[1]是否已经存在,如果已经存在则不创建选项?
编辑:在我的javascript中,
您可以使用来自angularui的唯一过滤器(这里提供的源代码:angularui unique filter),并直接在ng选项(或ng repeat)中使用它。
1 2 3 4 | <select ng-model="orderProp" ng-options="place.category for place in places | unique:'category'"> <option value="0">Default</option> // unique options from the categories </select> |
或者你也可以用lodash编写你自己的过滤器。
1 2 3 4 5 | app.filter('unique', function() { return function (arr, field) { return _.uniq(arr, function(a) { return a[field]; }); }; }); |
您可以在angular.filter模块中使用"unique"(别名:uniq)过滤器< BR>
用法:
您还可以按嵌套属性筛选:
你能做的就是这样……
1 2 3 4 5 6 7 8 9 | function MainController ($scope) { $scope.orders = [ { id:1, customer: { name: 'foo', id: 10 } }, { id:2, customer: { name: 'bar', id: 20 } }, { id:3, customer: { name: 'foo', id: 10 } }, { id:4, customer: { name: 'bar', id: 20 } }, { id:5, customer: { name: 'baz', id: 30 } }, ]; } |
HTML:我们按客户ID筛选,即删除重复的客户
1 2 3 4 | <th>Customer list: </th> <tr ng-repeat="order in orders | unique: 'customer.id'"> <td> {{ order.customer.name }} , {{ order.customer.id }} </td> </tr> |
结果客户名单:FO 10<BR/>Bar 20<BR/>baz 30
这个代码对我有效。
1 2 3 4 5 6 7 8 9 10 11 12 13 | app.filter('unique', function() { return function (arr, field) { var o = {}, i, l = arr.length, r = []; for(i=0; i<l;i+=1) { o[arr[i][field]] = arr[i]; } for(i in o) { r.push(o[i]); } return r; }; }) |
然后
1 | var colors=$filter('unique')(items,"color"); |
如果你想列出类别,我想你应该明确说明在观点上的意图。
1 2 3 4 5 6 | <select ng-model="orderProp"> <option ng-repeat="category in categories" value="{{category}}"> {{category}} </option> </select> |
在控制器中:
1 2 3 4 | $scope.categories = $scope.places.reduce(function(sum, place) { if (sum.indexOf( place.category ) < 0) sum.push( place.category ); return sum; }, []); |
下面是一个简单的通用示例。
过滤器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | sampleApp.filter('unique', function() { // Take in the collection and which field // should be unique // We assume an array of objects here // NOTE: We are skipping any object which // contains a duplicated value for that // particular key. Make sure this is what // you want! return function (arr, targetField) { var values = [], i, unique, l = arr.length, results = [], obj; // Iterate over all objects in the array // and collect all unique values for( i = 0; i < arr.length; i++ ) { obj = arr[i]; // check for uniqueness unique = true; for( v = 0; v < values.length; v++ ){ if( obj[targetField] == values[v] ){ unique = false; } } // If this is indeed unique, add its // value to our values and push // it onto the returned array if( unique ){ values.push( obj[targetField] ); results.push( obj ); } } return results; }; }) |
标记:
1 2 3 | {{ item.name }} <script src="your/filters.js"> |
我决定扩展@thethakuri的答案,以允许唯一成员具有任何深度。这是密码。这是为那些不想仅仅为了这个功能而包含整个Angularui模块的人准备的。如果您已经在使用Angularui,请忽略此答案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | app.filter('unique', function() { return function(collection, primaryKey) { //no need for secondary key var output = [], keys = []; var splitKeys = primaryKey.split('.'); //split by period angular.forEach(collection, function(item) { var key = {}; angular.copy(item, key); for(var i=0; i<splitKeys.length; i++){ key = key[splitKeys[i]]; //the beauty of loosely typed js :) } if(keys.indexOf(key) === -1) { keys.push(key); output.push(item); } }); return output; }; }); |
例子
1 |
更新
我建议使用set,但很抱歉,它不适用于ng repeat,也不适用于map,因为ng repeat只适用于array。所以忽略这个答案。无论如何,如果您需要过滤掉重复的内容,一种方法就像另一种方法使用
yo可以使用ecmascript 2015(es6)标准集数据结构,而不是数组数据结构,这样,在添加到集时可以过滤重复值。(记住设置不允许重复值)。非常容易使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | var mySet = new Set(); mySet.add(1); mySet.add(5); mySet.add("some text"); var o = {a: 1, b: 2}; mySet.add(o); mySet.has(1); // true mySet.has(3); // false, 3 has not been added to the set mySet.has(5); // true mySet.has(Math.sqrt(25)); // true mySet.has("Some Text".toLowerCase()); // true mySet.has(o); // true mySet.size; // 4 mySet.delete(5); // removes 5 from the set mySet.has(5); // false, 5 has been removed mySet.size; // 3, we just removed one value |
这是一个模板唯一的方法(但它不维护订单)。此外,还将对结果进行排序,这在大多数情况下都很有用:
1 2 3 4 5 | <select ng-model="orderProp"> <option ng-repeat="place in places | orderBy:'category' as sortedPlaces" data-ng-if="sortedPlaces[$index-1].category != place.category" value="{{place.category}}"> {{place.category}} </option> </select> |
上面的过滤器都没有解决我的问题,所以我不得不从正式的github文档中复制过滤器。然后按照上面的答案使用它
1 | angular.module('yourAppNameHere').filter('unique', function () { |
返回函数(items,filteron){
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | if (filterOn === false) { return items; } if ((filterOn || angular.isUndefined(filterOn)) && angular.isArray(items)) { var hashCheck = {}, newItems = []; var extractValueToCompare = function (item) { if (angular.isObject(item) && angular.isString(filterOn)) { return item[filterOn]; } else { return item; } }; angular.forEach(items, function (item) { var valueToCheck, isDuplicate = false; for (var i = 0; i < newItems.length; i++) { if (angular.equals(extractValueToCompare(newItems[i]), extractValueToCompare(item))) { isDuplicate = true; break; } } if (!isDuplicate) { newItems.push(item); } }); items = newItems; } return items; }; }); |
我有一个字符串数组,而不是对象,我使用了这种方法:
1 | ng-repeat="name in names | unique" |
使用此筛选器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | angular.module('app').filter('unique', unique); function unique(){ return function(arry){ Array.prototype.getUnique = function(){ var u = {}, a = []; for(var i = 0, l = this.length; i < l; ++i){ if(u.hasOwnProperty(this[i])) { continue; } a.push(this[i]); u[this[i]] = 1; } return a; }; if(arry === undefined || arry.length === 0){ return ''; } else { return arry.getUnique(); } }; } |
似乎每个人都把他们自己版本的
1 2 3 4 5 6 7 8 9 10 11 | angular.module('myFilters', []) .filter('unique', function () { return function (items, attr) { var seen = {}; return items.filter(function (item) { return (angular.isUndefined(attr) || !item.hasOwnProperty(attr)) ? true : seen[item[attr]] = !seen[item[attr]]; }); }; }); |
如果要基于嵌套键获取唯一数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | app.filter('unique', function() { return function(collection, primaryKey, secondaryKey) { //optional secondary key var output = [], keys = []; angular.forEach(collection, function(item) { var key; secondaryKey === undefined ? key = item[primaryKey] : key = item[primaryKey][secondaryKey]; if(keys.indexOf(key) === -1) { keys.push(key); output.push(item); } }); return output; }; }); |
这样称呼它:
1 |
添加此筛选器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | app.filter('unique', function () { return function ( collection, keyname) { var output = [], keys = [] found = []; if (!keyname) { angular.forEach(collection, function (row) { var is_found = false; angular.forEach(found, function (foundRow) { if (foundRow == row) { is_found = true; } }); if (is_found) { return; } found.push(row); output.push(row); }); } else { angular.forEach(collection, function (row) { var item = row[keyname]; if (item === null || item === undefined) return; if (keys.indexOf(item) === -1) { keys.push(item); output.push(row); } }); } return output; }; }); |
更新标记:
1 2 3 | <select ng-model="orderProp"> <option ng-repeat="place in places | unique" value="{{place.category}}">{{place.category}}</option> </select> |
创建自己的数组。
1 2 3 4 5 6 7 8 9 10 11 12 | <select name="cmpPro" ng-model="test3.Product" ng-options="q for q in productArray track by q"> <option value="">Plans</option> </select> productArray =[]; angular.forEach($scope.leadDetail, function(value,key){ var index = $scope.productArray.indexOf(value.Product); if(index === -1) { $scope.productArray.push(value.Product); } }); |
这可能有点过分,但对我有用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | Array.prototype.contains = function (item, prop) { var arr = this.valueOf(); if (prop == undefined || prop == null) { for (var i = 0; i < arr.length; i++) { if (arr[i] == item) { return true; } } } else { for (var i = 0; i < arr.length; i++) { if (arr[i][prop] == item) return true; } } return false; } Array.prototype.distinct = function (prop) { var arr = this.valueOf(); var ret = []; for (var i = 0; i < arr.length; i++) { if (!ret.contains(arr[i][prop], prop)) { ret.push(arr[i]); } } arr = []; arr = ret; return arr; } |
distinct函数依赖于上面定义的contains函数。它可以称为
所以你可以直接说"EDOCX1"〔4〕。