我有一些文章。例如:
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写一下还是更好的?
答案 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'}))