How to make ng-repeat filter out duplicate results

前端 未结 16 2687
鱼传尺愫
鱼传尺愫 2020-11-22 06:52

I\'m running a simple ng-repeat over a JSON file and want to get category names. There are about 100 objects, each belonging to a category - but there are only

相关标签:
16条回答
  • 2020-11-22 07:12

    None of the above filters fixed my issue so I had to copy the filter from official github doc. And then use it as explained in the above answers

    angular.module('yourAppNameHere').filter('unique', function () {
    

    return function (items, filterOn) {

    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;
      };
    
    });
    
    0 讨论(0)
  • 2020-11-22 07:13

    I decided to extend @thethakuri's answer to allow any depth for the unique member. Here's the code. This is for those who don't want to include the entire AngularUI module just for this functionality. If you're already using AngularUI, ignore this answer:

    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;
        };
    });
    

    Example

    <div ng-repeat="item in items | unique : 'subitem.subitem.subitem.value'"></div>
    
    0 讨论(0)
  • 2020-11-22 07:13

    This might be overkill, but it works for me.

    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;
    }
    

    The distinct function depends on the contains function defined above. It can be called as array.distinct(prop); where prop is the property you want to be distinct.

    So you could just say $scope.places.distinct("category");

    0 讨论(0)
  • 2020-11-22 07:16

    Create your own array.

    <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);
        }
    });
    
    0 讨论(0)
  • 2020-11-22 07:17

    UPDATE

    I was recomending the use of Set but sorry this doesn't work for ng-repeat, nor Map since ng-repeat only works with array. So ignore this answer. anyways if you need to filter out duplicates one way is as other has said using angular filters, here is the link for it to the getting started section.


    Old answer

    Yo can use the ECMAScript 2015 (ES6) standard Set Data structure, instead of an Array Data Structure this way you filter repeated values when adding to the Set. (Remember sets don't allow repeated values). Really easy to use:

    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
    
    0 讨论(0)
  • 2020-11-22 07:18

    Here's a straightforward and generic example.

    The filter:

    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;
      };
    })
    

    The markup:

    <div ng-repeat = "item in items | unique:'name'">
      {{ item.name }}
    </div>
    <script src="your/filters.js"></script>
    
    0 讨论(0)
提交回复
热议问题