简体   繁体   English

根据匹配的数据返回数组中的对象

[英]Return Object in Array based on matched data

I have a json array of about 30 objects. 我有大约30个对象的json数组。 Here's a sample object from the array: 这是数组中的一个示例对象:

{
    "id": 0,
    "name": "Valle",
    "activities": "night-life",
    "food": "fancy-food",
    "sport" : "baseball",
    "geoProfile": "artsy",
    "priority": 2
}

I am building out another object on a page based on user input. 我正在根据用户输入在页面上构建另一个对象。 The user will choose between radio buttons and after they have made their choices, I will have an object such as: 用户将在单选按钮之间进行选择,并且在做出选择之后,我将拥有一个对象,例如:

{geoProfile: "artsy", activities: "nature", food: "fancy-food", sport: "cricket"}

I am using jQuery's $.each() method to go through each object as follows: 我正在使用jQuery的$.each()方法来遍历每个对象,如下所示:

$.each(self.data(), function (i, s) {
    if (s.geoProfile == self.prefLocation() &&
        s.activities == self.prefActivity() &&
        s.food == self.prefFood() &&
        s.sport == self.prefSport()) {
        optionMatched = s;
        return false;
    }
});

This will return an object that has all four matches, but how can I return the json object that has the most matches to the user-built object? 这将返回具有所有四个匹配项的对象,但是如何返回与用户构建的对象匹配度最高的json对象? If two match, I want to then look at the "priority" property and return the one with the lowest priority. 如果两个匹配,那么我想查看“优先级”属性并返回优先级最低的属性。

You could use Array#map and build a new array with the sum of the matched properties. 您可以使用Array#map并使用匹配属性的总和构建一个新数组。

Later you can sort with map and use the result for sorting and get the first element. 稍后,您可以使用map进行排序,并将结果用于排序并获取第一个元素。

var data = [/* your data here */],
    search = { geoProfile: "artsy", activities: "nature", food: "fancy-food", sport: "cricket" },
    result = data.map(function (a, i) {
        return {
            count: Object.keys(search).reduce(function (r, k) { return r + +(a[k] === search[k]); }, 0),
            priority: a.priority,
            index: i
        }
    });

result.sort(function (a, b) {
    return b.count - a.count || a.priority - b.priority;
});

A single loop solution 单回路解决方案

var data = [/* your data here */],
    search = { geoProfile: "artsy", activities: "nature", food: "fancy-food", sport: "cricket" },
    result = data.reduce(function (r, a, i) {
        document.write('<pre>' + JSON.stringify(r, 0, 4) + '</pre><hr>');
        var o = {
            count: Object.keys(search).reduce(function (q, k) { return q + +(a[k] === search[k]); }, 0),
            priority: a.priority,
            index: i
        };
        if (!i || o.count > r[0].count || o.count === r[0].count && o.priority < r[0].priority) {
            return [o];
        }
        o.count === r[0].count && o.priority === r[0].priority && r.push(o);
        return r;
    }, []);

Just track the number of matches and update your selected one based on if it has more matches. 只需跟踪匹配数并根据是否有更多匹配项来更新您选择的匹配项即可。

var numOfMatches = 0;
$.each(self.data(), function(i, s) {
  var matchingProperties = 0;
  if (s.geoProfile == self.prefLocation()) {
    matchingProperties++;
  }
  if (s.activities == self.prefActivity()) {
    matchingProperties++;
  }
  if (s.food == self.prefFood()) {
    matchingProperties++;
  }
  if (s.sport == self.prefSport()) {
    matchingProperties++;
  }

  if (matchingProperties === 0 || matchingProperties < numOfMatches) {
    return;
  }

  if (!optionMatched // Grab the first match
      || matchingProperties > numOfMatches // or if more properties match
      || s.priority < optionMatched.priority) { // or the one with a lower priority
    optionMatched = s;
    numOfMatches = matchingProperties;
  }
});

Or you could simplify the initial counting using filter : 或者您可以使用filter简化初始计数:

var numOfMatches = 0;
$.each(self.data(), function(i, s) {
  var matchingProperties = [
    s.geoProfile == self.prefLocation(),
    s.activities == self.prefActivity(),
    s.food == self.prefFood(),
    s.sport == self.prefSport()
  ].filter(function(val) { return val; }).length;

  if (matchingProperties === 0 || matchingProperties < numOfMatches) {
    return;
  }

  if (!optionMatched // Grab the first match
      || matchingProperties > numOfMatches // or if more properties match
      || s.priority < optionMatched.priority) { // or the one with a lower priority
    optionMatched = s;
    numOfMatches = matchingProperties;
  }
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM