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

Json 如何根据另一个对象的匹配值筛选或自定义筛选对象数组,json,angularjs,Json,Angularjs,我在AngularJS中用15个输入字段实现了一个高级搜索 在页面加载本身中,结果集是以JSON格式从数据库返回的,我只需要在客户端进行过滤 输入条件的等效列在结果集中可用,我只需要在其各自的列中进行检查 我通过JSON.stringify()转换每个列,并使用如下搜索参数进行检查: $scope.filteredData = $scope.actualData.filter(function(item) { return JSON.stringify(item.FirstName).t

我在
AngularJS
中用15个输入字段实现了一个高级搜索

在页面加载本身中,结果集是以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个输入字段的示例代码:

首先,你
ng repeter
的50000条记录很可能会杀死你的浏览器,所以你应该考虑分页。 第二,你可以很容易地过滤你的数据使用角度过滤器请看演示



名字:
姓氏:
电子邮件地址:
地址1:
地址2:
搜寻

过滤数据: | 地址:{data.Address1}

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

为了浏览器和服务器,您确实需要限制来自服务器的数据。很容易实现限制、补偿系统。听起来,总体而言,您只需要能够查询服务器上的某个记录

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

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

最后,为了完美地模拟
过滤器:searchParams
,您只需在有用户输入且输入足够长以开始部分匹配之前进行检查,以不过滤项目


你为什么还要调用
JSON.stringify()
?结果数据已经是具有字符串属性的对象。只需执行
item.FirstName.toLowerCase().indexOf(..)
plunker不会为任何有效输入返回任何筛选数据。@Arulkumar确实如此。我的代码执行您的代码试图执行的操作,这可能根本不是您想要的(就像我在回答中所说的)。你明白我说的吗?我做了你做的事,但是对。我的猜测是,您不希望代码尝试生成的结果,特别是因为该结果没有任何意义。无论如何,就像您的代码一样,对于所有的
&&
,如果所有输入都匹配,我的示例将显示该对象。我真的认为你想要西尔维斯特的答案,或者也许我的答案是使用
。取而代之的是一些
,这将类似于西尔维斯特的anwer,但行为略有不同。@Arulkumar这里使用
也有同样的事情。一些
对象会显示在任何字段完全匹配的地方,即它们输入全名“Arul”,然后输入“Arul”对象显示。也许这就是你想要的。首先感谢你的努力、时间和详细的回复。我能理解你的意图。Sylvester的答案是用结果集的所有字段搜索输入的字段。我的要求是,如果我在firstname输入字段中键入'Arul',那么我只需要在json的firstname字段中搜索'Arul',而不需要在其他字段中搜索。除了部分关键字搜索外,您的结果按预期工作,这意味着即使我在名字的输入字段中键入“Ar”,我也希望得到结果。因此,除了“.some”之外,我们还可以使用其他选项来实现这一点吗?@Arulkumar我在回答中添加了很多内容。我想您现在已经意识到,
filter:searchParams
一直以来都在做您想要的事情,但是我重新创建了它的行为,以便您能够更好地理解它在做什么,并根据需要定制确切的行为。我的要求是使用json的相应列搜索输入字段。因此,如果我在输入字段的FirstName中输入'Ar',过滤后的结果需要获取与json FirstName字段的匹配项。您的代码也返回了与其他列的所有匹配项。@Arulkumar请参见此处第二个用户名是Arul,但如果您在名字中键入“ar”,则只得到第一个用户,我没有检查这一点。谢谢你通知我。
<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>
<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();
      });
    };
  };
  $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;
      });
    };
  };
  $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;
      });
    };
  };