简体   繁体   English

按匹配的对象字段数排序对象数组

[英]sort array of objects by number of object fields matched

I have the following object: 我有以下对象:

var entries = [
  {
    fields: {
      tags: [
        { fields: { id: "football" } },
        { fields: { id: "running" } },
        { fields: { id: "tennis" } }
      ]
    }
  },
  {
    fields: {
      tags: [
        { fields: { id: "tennis" } },
        { fields: { id: "football" } },
        { fields: { id: "rugby" } }
      ]
    }
  },
  {
    fields: {
      tags: [
        { fields: { id: "cricket" } },
        { fields: { id: "running" } }
      ]
    }
  },
  {
    fields: {
      tags: [
        { fields: { id: "football" } },
        { fields: { id: "rugby" } }
      ]
    }
  }
];

Now, I want to sort the array using another array: var testArray = ["football", "rugby"] 现在,我想使用另一个数组对数组进行排序: var testArray = ["football", "rugby"]

So any of the objects that contain both rugby and football in their fields.tags.fields.id should return first in the array, then any that just contain 1 should appear next. 因此,在其fields.tags.fields.id同时包含rugbyfootball任何对象都应在数组中首先返回,然后仅包含1的任何对象都应出现在数组中。 So the results I'm after would be: 所以我想要的结果是:

var sortedEntries = [
  {
    fields: {
      tags: [
        { fields: { id: "tennis" } },
        { fields: { id: "football" } },
        { fields: { id: "rugby" } }
      ]
    }
  },
  {
    fields: {
      tags: [
        { fields: { id: "football" } },
        { fields: { id: "rugby" } }
      ]
    }
  },
  {
    fields: {
      tags: [
        { fields: { id: "football" } },
        { fields: { id: "running" } },
        { fields: { id: "tennis" } }
      ]
    }
  },
  {
    fields: {
      tags: [
        { fields: { id: "cricket" } },
        { fields: { id: "running" } }
      ]
    }
  }
];

I thought this might be possible using the sort() function but then I realised I need to compare my testArray to see how many items are matched. 我以为可以使用sort()函数来做到这一点,但后来我意识到我需要比较testArray来查看匹配了多少项。 Is this possible? 这可能吗? I can't find any examples online of what I'm trying to do and I don't know where to begin. 我在网上找不到任何我想做的事的例子,也不知道从哪里开始。

Custom sort function that filters the tags arrays and checks lengths of those matches 自定义排序功能,用于过滤标签数组并检查匹配项的长度

entries.sort(function (a, b) {
    var aMatches = a.fields.tags.filter(function (item) {
        return testArray.indexOf(item.fields.id) > -1
    });
    var bMatches = b.fields.tags.filter(function (item) {
        return testArray.indexOf(item.fields.id) > -1
    });
    return bMatches.length - aMatches.length;
});

DEMO 演示

Solution optimized for large datasets, with temporary storage of count. 针对大型数据集优化的解决方案,具有临时存储计数的功能。

 var search = ['football', 'rugby'], entries = [{ fields: { tags: [{ fields: { id: "cricket" } }, { fields: { id: "running" } }] } }, { fields: { tags: [{ fields: { id: "football" } }, { fields: { id: "running" } }, { fields: { id: "tennis" } }] } }, { fields: { tags: [{ fields: { id: "tennis" } }, { fields: { id: "football" } }, { fields: { id: "rugby" } }] } }, { fields: { tags: [{ fields: { id: "football" } }, { fields: { id: "rugby" } }] } }], sortedData = entries.map(function (a) { a.count = a.fields.tags.reduce(function (r, b) { return r + !!~search.indexOf(b.fields.id); }, 0); return a; }, []).sort(function (a, b) { return b.count - a.count; }).map(function (a) { delete a.count; return a; }, []); document.write('<pre>' + JSON.stringify(sortedData, 0, 4) + '</pre>'); 

Solution optimized for small datasets, without temporary storage of count. 针对小型数据集优化的解决方案,无需临时存储计数。

 var search = ['football', 'rugby'], entries = [{ fields: { tags: [{ fields: { id: "cricket" } }, { fields: { id: "running" } }] } }, { fields: { tags: [{ fields: { id: "football" } }, { fields: { id: "running" } }, { fields: { id: "tennis" } }] } }, { fields: { tags: [{ fields: { id: "tennis" } }, { fields: { id: "football" } }, { fields: { id: "rugby" } }] } }, { fields: { tags: [{ fields: { id: "football" } }, { fields: { id: "rugby" } }] } }], sortedData = entries.sort(function (a, b) { function f(r, c) { return r + !!~search.indexOf(c.fields.id); } return b.fields.tags.reduce(f, 0) - a.fields.tags.reduce(f, 0); }); document.write('<pre>' + JSON.stringify(sortedData, 0, 4) + '</pre>'); 

It's possible with a custom sort function that would check how many items in tags exist in testArray . 可以使用自定义排序功能来检查testArraytags存在多少个项目。 Something like this should work: 这样的事情应该起作用:

var testArray = ["football", "rugby"];
entries.sort(function(a, b) {
    var a_score = 0;
    var b_score = 0;
    for (var i=0; i<a.fields.tags.length; i++) {
        if (testArray.indexOf(a.fields.tags[i]) > -1) {
            a_score++;
        }
    }
    for (var i=0; i<b.fields.tags.length; i++) {
        if (testArray.indexOf(b.fields.tags[i]) > -1) {
            b_score++;
        }
    }
    return b_score-a_score;
});

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

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