我正在创建一个Todo App,作为学习PostgreSQL和使用JavaScript进行功能编程的练习。这个想法是,可以有多个容器,每个容器都有单独的过滤器设置,每个容器从Todos的主列表中读取数据,然后每个容器根据其过滤器设置显示其结果。这实际上是在React-Redux和Nodejs中完成的,但是我在下面的示例中做了更好的说明。
数据:
// Example todos
let a = {
added: "2021-02-01T05:00:00.000Z",
completed: null,
description: "This is just a test.",
name: "testing",
tags: [],
todo_id: 3,
}
let b = {
added: "2021-02-01T05:00:00.000Z",
completed: null,
description: "This is just a test.",
name: "testing",
tags: ["one", "two"],
todo_id: 4
}
let c = {
added: "2021-02-01T05:00:00.000Z",
completed: null,
description: "This is just a test.",
name: "tesin",
tags: ["one"],
todo_id: 5
}
let d = {
added: "2021-02-01T05:00:00.000Z",
completed: '2021-03-01T05:00:00.000Z',
description: "This is just a test.",
name: "testing",
tags: ["two", "testing"],
todo_id: 6
}
// Example filter_group
// This is just to show what the initial state looks like in my React app
const filter_groups = {
"main": {
byTag: 'two',
byName: '',
byCompleted: true
}
}
// Object.keys(filter_groups).map() passes the filter settings down as props
// Just stuck it in a variable for the example
const filter = filter_groups['main']
// Putting example Todos in array
const todo_list = [a,b,c,d]
当前的解决方案非常简单,丑陋且效率低下。它一次应用每个过滤器:
// ------- CURRENT SOLUTION -------
// if user is trying to filter byCompleted, then filter todo_list
// else do nothing todo_list and pass it to the next filter
// (similar thing applies down the chain)
const byCompleted = filter.byCompleted === true ?
todo_list.filter ( (t) => {
return t.completed !== null
})
:
todo_list
//IF user is trying to filter byTag...
const byTag = filter.byTag !== '' ?
// THEN filter the byCompleted array above
byCompleted.filter( (t) => {
// IF there are tags on the Todo...
let matches = t.tags ?
// THEN filter for matches
t.tags.filter( (tag) => {
return tag === filter.byTag
})
:
// ELSE make this an empty array
[]
// return any Todos with match
return matches.length > 0
})
:
byCompleted
// IF user is trying to filter byName...
const byName = filter.byName !== '' ?
// THEN filter byTag Todos
byTag.filter( (t) => {
return t.name === P.filter.byName
})
:
byTag
console.log(byName);
我真的很想知道是否有一种方法可以一次全部应用整个过滤器。在示例中,您将看到过滤器设置为byTag: 'two', byComplete: true
使控制台仅输出一个结果的过滤器。我过去尝试通过一次过滤器传递使事情生效的尝试将返回带有two
标签的所有内容。
我尝试查看了文档,发现过滤器功能还有更多功能,但是并没有点击,并且找不到适合我的用例的示例。
编辑:这是codeandbox上的全部内容:https ://codesandbox.io/s/recursing-almeida-cdz65 ? file =/ src/index.js
您在问题中提到了函数编程。
下面的代码采用一种简单的方法来解决您的过滤问题。
一旦建立了单独的过滤器,将它们链接在一起就很简单。每个过滤器函数将返回一个数组,以供下一个函数操作。
注意:我必须推断一些细节。
let a = { added: "2021-02-01T05:00:00.000Z", completed: null, description: "This is just a test.", name: "testing", tags: [], todo_id: 3, }
let b = { added: "2021-02-01T05:00:00.000Z", completed: null, description: "This is just a test.", name: "testing", tags: ["one", "two"], todo_id: 4 }
let c = { added: "2021-02-01T05:00:00.000Z", completed: null, description: "This is just a test.", name: "tesin", tags: ["one"], todo_id: 5 }
let d = { added: "2021-02-01T05:00:00.000Z", completed: '2021-03-01T05:00:00.000Z', description: "This is just a test.", name: "testing", tags: ["two", "testing"], todo_id: 6 }
const filter_groups = { "main": { byTag: 'two', byName: '', byCompleted: true } }
const filter = filter_groups['main']
const todo_list = [a,b,c,d]
let byTag = td => td.tags.includes(filter.byTag);
let byName = td => filter.name ? td.tags.includes(filter.name) : true;
let byCompleted = td => filter.byCompleted ? td.completed !== null : false ;
let result = todo_list.filter(byTag).filter(byName).filter(byCompleted);
console.log(result);
编辑:OP要求在一个代码块中执行此操作。该解决方案如下:
let a = { added: "2021-02-01T05:00:00.000Z", completed: null, description: "This is just a test.", name: "testing", tags: [], todo_id: 3, };
let b = { added: "2021-02-01T05:00:00.000Z", completed: null, description: "This is just a test.", name: "testing", tags: ["one", "two"], todo_id: 4 };
let c = { added: "2021-02-01T05:00:00.000Z", completed: null, description: "This is just a test.", name: "tesin", tags: ["one"], todo_id: 5 };
let d = { added: "2021-02-01T05:00:00.000Z", completed: '2021-03-01T05:00:00.000Z', description: "This is just a test.", name: "testing", tags: ["two", "testing"], todo_id: 6 };
const todo_list = [a,b,c,d];
const filter_groups = { "main": { tags: 'two', name: '', completed: true } };
let result2 = todo_list.filter(td=>{
return Object.entries(filter_groups['main'])
.filter(([k,v])=>!!v!=false)
.map(f=>!!td[f[0]])
.every(f=>f==true);
});
console.log(result2);
OP还提到了他原始代码和“三步走”解决方案中有关性能的问题。
为了给您以通常的方式编写代码的信心,我使用jsben.ch.com进行了一系列测试。下图显示了OP的原始代码始终位于#2或#1处。“三步走”解决方案分享了这一结果。最重要的是,更多的步骤不一定等同于性能较差。如果可以让站点进行合作,请多次运行测试以了解性能差异。JSBEN.CH测试
用一粒盐获得这些结果-很好地显示了比较,但没有太多其他好处。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句