Javascript 正确筛选具有多个条件和一个数组的对象数组

Javascript 正确筛选具有多个条件和一个数组的对象数组,javascript,functional-programming,Javascript,Functional Programming,我正在创建一个Todo应用程序,作为学习PostgreSQL和javascript函数编程的练习。其思想是可以有多个容器,每个容器都有单独的过滤器设置,每个容器都从TODO的主列表中读取,然后每个容器根据其过滤器设置显示其结果。这实际上都是在React-Redux和Nodejs中完成的,但是为了更好地说明这个问题,我做了下面的示例 数据: // Example todos let a = { added: "2021-02-01T05:00:00.000Z", com

我正在创建一个Todo应用程序,作为学习PostgreSQL和javascript函数编程的练习。其思想是可以有多个容器,每个容器都有单独的过滤器设置,每个容器都从TODO的主列表中读取,然后每个容器根据其过滤器设置显示其结果。这实际上都是在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
标记的内容

我试着查看文档,发现filter函数中还有更多内容,但它没有点击,我也找不到任何非常适合我的用例的示例


编辑:下面是代码沙盒的全部内容:

您在问题中提到了函数编程

下面的代码采用一种通用的方法来解决过滤问题

一旦建立了各个过滤器,就只需将它们链接在一起。每个过滤器函数将返回一个数组,供下一个函数操作

注:我不得不推断出一些细节

let a={添加:“2021-02-01T05:00:00.000Z”,完成:null,描述:“这只是一个测试”,名称:“测试”,标记:[],todo_id:3,}
让b={添加:“2021-02-01T05:00:00.000Z”,完成:null,描述:“这只是一个测试”,名称:“测试”,标记:[“一”,“二”],todo_id:4}
让c={添加:“2021-02-01T05:00:00.000Z”,完成:null,描述:“这只是一个测试”,名称:“tesin”,标记:[“一个”],todo_id:5}
让d={添加:“2021-02-01T05:00:00.000Z”,完成:“2021-03-01T05:00:00.000Z”,描述:“这只是一个测试”,名称:“测试”,标签:[“两个”,“测试”],todo_id:6}
const filter_groups={“main”:{byTag:'two',byName:'',byCompleted:true}
常量过滤器=过滤器组['main']
常量待办事项列表=[a、b、c、d]
让byTag=td=>td.tags.includes(filter.byTag);
让byName=td=>filter.name?td.tags.includes(filter.name):true;
让byCompleted=td=>filter.byCompleted?td.已完成!==null:false;
让result=todo_list.filter(按标签)、filter(按名称)、filter(按完成);

控制台日志(结果)这看起来非常干净,是非常有用的答案。我必须编辑
let byCompleted=td=>filter.byCompleted?td.已完成!==null:true,但我想我在我的帖子中并没有说得很清楚。抱歉,但我也有点担心速度(不是太多,因为它对应用程序很重要,只是好奇),这看起来仍然会有3个单独的通行证?我知道每通过一次,事情的大小都会减少,但是,如果可能的话,我还是想知道如何通过一次通过来实现这一切。单个步骤是函数式编程的本质。正如您所发现的,在一个大的块中编写这个会变得混乱,特别是因为条件的相互依赖性。我会买更干净、更容易维护的代码,而不是一周中任何一天快几毫秒的代码。我会看一看。非常感谢您的帮助!这是一次很棒的学习经历,我真的很惊讶我原来的解决方案做得这么好。我真的觉得我对这类事情还没有完全掌握。你对学习这类东西的资源有什么建议吗?我很乐意提供帮助。我很难接受“学习资源”这个概念,因为我坚信人与人之间的互动是最好的学习方法。没有导师/老师的自学能力有限。话虽如此,我显然找不到有人为例子的教程网站,它们不能真正反映现实世界。所以,我想我能提供的最好的资源出现在。浏览教程和参考资料中的主题。那就选一个吧!