按对象的字段过滤对象数组,其中包含数组

时间:2017-03-19 12:24:17

标签: javascript arrays

我有一些文章。例如:

var articles = [
    {
        id: '1',
        createdAt: new Date(2017, 3, 5, 8, 0),
        title: '«Title 1',
        summary: 'Summary 1',
        author: 'John',
        content: 'Content 1',
        tags: ['tag1'],
    },
    {
        id: '2',
        createdAt: new Date(2017, 4, 5, 8, 0),
        title: '«Title 2',
        summary: 'Summary 2',
        author: 'Bob',
        content: 'Content 2',
        tags: ['tag1', 'tag2'],
    },
    {
        id: '3',
        createdAt: new Date(2017, 5, 5, 8, 0),
        title: '«Title 3',
        summary: 'Summary 3',
        author: 'Jeremy',
        content: 'Content 3',
        tags: ['tag2'],
}];

我有filterConfig

var filterConfig =
{
    createdAtFrom: new Date(2017, 3, 5, 8, 0),
    createdAtTo:new Date(2017, 5, 5, 8, 0),
    author: 'Bob',
    tags: ['tag1,tag2'],
};

所以我需要通过此过滤器配置过滤我的文章。它可以包含所有字段或其中一些字段。而我的函数getArticles应该返回过滤后的文章数组。过滤的数组也应该包含filterConfig中提到的所有标记,但如果文章包含3个标记,其中2个在filterConfig中,则函数应该返回它。还有filterConfig中的文章。 在我的例子中,如果应该返回

{
    id: '2',
    createdAt: new Date(2017, 4, 5, 8, 0),
    title: '«Title 2',
    summary: 'Summary 2',
    author: 'Bob',
    content: 'Content 2',
    tags: ['tag1', 'tag2'],
}

如果最好的方法怎么办?我应该为所有的filds写一下还是更好的?

2 个答案:

答案 0 :(得分:1)

您似乎有四种类型的测试:从测试,到测试,数组测试和相等测试。

我会迭代数组,然后遍历每个配置属性,最后检测必须执行的四个测试中的哪一个,并执行它。

以下是一些ES6代码:

articles.filter( article => {
    return Object.keys(filterConfig).every( key => {
        const [prop, operator] = key.match(/^(.*?)(From|To)?$/).slice(1),
            value = article[prop],
            testValue = filterConfig[key];
        return operator === 'From' ? value >= testValue
             : operator === 'To' ? value <= testValue
             : Array.isArray(value) ? testValue.every( test => value.includes(test) )
             : value === testValue;
    });
});

var articles = [
{
    id: '1',
    createdAt: new Date(2017, 3, 5, 8, 0),
    title: '«Title 1',
    summary: 'Summary 1',
    author: 'John',
    content: 'Content 1',
    tags: ['tag1'],
},
{
    id: '2',
    createdAt: new Date(2017, 4, 5, 8, 0),
    title: '«Title 2',
    summary: 'Summary 2',
    author: 'Bob',
    content: 'Content 2',
    tags: ['tag1', 'tag2'],
},
{
    id: '3',
    createdAt: new Date(2017, 5, 5, 8, 0),
    title: '«Title 3',
    summary: 'Summary 3',
    author: 'Jeremy',
    content: 'Content 3',
    tags: ['tag2'],
}];

var filterConfig = {
    createdAtFrom: new Date(2017, 3, 5, 8, 0),
    createdAtTo:new Date(2017, 5, 5, 8, 0),
    author: 'Bob',
    tags: ['tag1','tag2'],
};

const result = articles.filter( article => {
    return Object.keys(filterConfig).every( key => {
        const [prop, operator] = key.match(/^(.*?)(From|To)?$/).slice(1),
            value = article[prop],
            testValue = filterConfig[key];
        return operator === 'From' ? value >= testValue
             : operator === 'To' ? value <= testValue
             : Array.isArray(value) ? testValue.every( test => value.includes(test) )
             : value === testValue;
    });
});

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

注意:tags属性在您的问题中存在问题:数组只有一个值。我认为它必须是['tag1','tag2']而不是['tag1,tag2']

答案 1 :(得分:0)

我认为您需要为过滤器配置中的每个属性编写一个if块,因为它们是可选的。

一种方法是对filterConfig中的每个属性运行一个测试。如果失败,则在过滤器中返回false,最后返回true。因此,默认情况下,每篇文章都会包含在结果中,除非它的某个过滤器检查失败。

Here is something to get you started

  var articles = [
    {
        id: '1',
        createdAt: new Date(2017, 3, 5, 8, 0),
        title: '«Title 1',
        summary: 'Summary 1',
        author: 'John',
        content: 'Content 1',
        tags: ['tag1'],
    },
    {
        id: '2',
        createdAt: new Date(2017, 4, 5, 8, 0),
        title: '«Title 2',
        summary: 'Summary 2',
        author: 'Bob',
        content: 'Content 2',
        tags: ['tag1', 'tag2'],
    },
    {
        id: '3',
        createdAt: new Date(2017, 5, 5, 8, 0),
        title: '«Title 3',
        summary: 'Summary 3',
        author: 'Jeremy',
        content: 'Content 3',
        tags: ['tag2'],
}];

var filterConfig =
{
    createdAtFrom: new Date(2017, 3, 5, 8, 0),
    createdAtTo:new Date(2017, 5, 5, 8, 0),
    author: 'Bob',
    tags: ['tag1,tag2'],
};


function filterArticles(articles, config){

return articles.filter(function(a){


if(config.createdAtFrom && config.createdAtFrom < a.createdAt){
return false;
}
if(config.createdAtTo && config.createdAtTo > a.createdAt){
return false;
}

if(config.author && config.author  !== a.author){
return false;
}

if(config.tags){
 for (var i = 0; i < config.tags.length; i++) {
        if(atricle.tags.indexOf(config.tags[i]) === -1 ){
        return false;
        }   
    }
}


return true;

});

}

console.log(filterArticles(articles, filterConfig))

console.log(filterArticles(articles, {  author: 'John'}))