代码之家  ›  专栏  ›  技术社区  ›  Arulkumar KP.

如何根据另一个对象的匹配值筛选或自定义筛选对象数组

  •  2
  • Arulkumar KP.  · 技术社区  · 9 年前

    我在 AngularJS .

    在页面加载本身中,结果集从 JSON格式 我需要进行过滤 客户端 只有

    输入条件的等效列在结果集中可用,我只需要检查其相应的列。

    我通过以下方式转换每一列 JSON.stringify() 并使用如下搜索参数进行检查:

    $scope.filteredData = $scope.actualData.filter(function(item) {
        return JSON.stringify(item.FirstName).toLowerCase().indexOf(lowerFirstName) != -1 &&
        JSON.stringify(item.LastName).toLowerCase().indexOf(lowerLastName) != -1 &&
        JSON.stringify(item.EmailAddress).toLowerCase().indexOf(lowerEmailAddress) != -1 &&
        JSON.stringify(item.Address1).toLowerCase().indexOf(lowerAddress1) != -1 &&
        JSON.stringify(item.Address2).toLowerCase().indexOf(lowerAddress2) != -1;
        ...... etc // upto 15 fields
    });
    

    因为我有15个输入字段,而实际结果集至少包含50000条记录。

    因此,通过 JSON.stringify() 检查搜索参数肯定会导致性能问题。

    有没有其他方法可以用其他方法在客户端实现过滤。

    我在Plunker中发布了一个示例代码,只有5个输入字段: http://plnkr.co/edit/nUWZEbGvz7HG6gb91YZP

    2 回复  |  直到 9 年前
        1
  •  2
  •   m59    9 年前

    西维斯特的答案是你过滤事物的正常方式。您的代码看起来只想过滤到与每个输入字段匹配的对象。代码尝试查找每个属性都与searchParams对象匹配的对象。在这一点上,我看不出找到该对象有什么好处,因为用户已经再次创建了该对象!尽管如此,这里有一个正确的代码版本:

    Live demo here.

    <div ng-repeat="data in actualData | filter:searchData()">
    
     $scope.searchData = function() {
        return function(item) {
          return Object.keys(item).every(function(key) {
            // skip the $$hashKey property Angular adds to objects
            if (key === '$$hashKey') { return true; }
            var searchKey = key.charAt(0).toLowerCase()+key.slice(1);
            return item[key].toLowerCase() === $scope.searchParams[searchKey].toLowerCase();
          });
        };
      };
    

    为了浏览器和服务器,您确实需要限制来自服务器的数据。实现LIMIT,OFFSET系统很容易。总的来说,您只需要能够向服务器查询特定的记录。

    从您的评论来看,似乎您肯定希望Angular内置过滤器 filter:searchParams ,然后将您的 searchParams 模型以匹配您的数据。为了好玩,我将提供更多的选项来进行更精细的调整。

    这个几乎模仿了 过滤器:searchParams 。您可以更改 > 1 当部分匹配开始时进行调整,或者只有当两项完全相等时才返回true === 以禁用部分匹配。这里的不同之处在于,所有项目在匹配之前都是隐藏的,而 过滤器:searchParams 将显示所有项目,然后删除不匹配的项目。

    Live demo here.

      $scope.searchData = function() {
        return function(item) {
          return Object.keys(item).some(function(key) {
            if (key === '$$hashKey') { return false; }
            var searchKey = key.charAt(0).toLowerCase()+key.slice(1);
            var currentVal = $scope.searchParams[searchKey].toLowerCase();
            var match = item[key].toLowerCase().match(currentVal);
            return currentVal.length > 1 && match;
          });
        };
      };
    

    最后,完美模仿 过滤器:searchParams ,您只需输入一个复选框,在有用户输入且输入足够长以开始部分匹配之前,不要过滤项目。

    Live demo here.

      $scope.searchData = function() {
        var partialMatchLength = 2;
        return function(item) {
          var shouldFilter = Object.keys($scope.searchParams).some(function(key) {
            return $scope.searchParams[key] && $scope.searchParams[key].length >= partialMatchLength;
          });
          if (!shouldFilter) { return true; }
          return Object.keys(item).some(function(key) {
            if (key === '$$hashKey') { return false; }
            var searchKey = key.charAt(0).toLowerCase()+key.slice(1);
            var currentVal = $scope.searchParams[searchKey].toLowerCase();
            var match = item[key].toLowerCase().match(currentVal);
            return currentVal.length >= partialMatchLength && match;
          });
        };
      };
    
        2
  •  1
  •   sylwester    9 年前

    首先你 ng-repeter 如果有50000条记录,很可能会杀死你的浏览器,所以你应该考虑分页。 其次,您可以使用角度过滤器轻松过滤数据,请参见演示

    http://plnkr.co/edit/R8b8G4xCMSQmX1144UJG?p=preview

    <div ng-controller="ListCtrl">
        <br />
        First Name:
        <input type="text" id="txtFirstname" ng-model="searchParams.FirstName">
        <br/>Last Name:
        <input type="text" id="txtLastname" ng-model="searchParams.LastName">
        <br/>Email Address:
        <input type="text" id="txtEmailAddress" ng-model="searchParams.EmailAddress">
        <br/>Address 1:
        <input type="text" id="txtAddress1" ng-model="searchParams.Address1">
        <br/>Address 2:
        <input type="text" id="txtAddress2" ng-model="searchParams.Address2">
        <br/>
        <button class="btn btn-primary" ng-click="searchData()">Search</button>
        <br />
        <hr />
        <b>Filtered Data(s):</b>
        <div ng-repeat="data in actualData | filter:searchParams ">
          <span ng-bind="data.FirstName"></span>
          <span ng-bind="data.LastName"></span> |
          Address : {{data.Address1}}
        </div>
        <hr />
    
      </div>