简体   繁体   English

有没有更好的方法在 JavaScript 中编写冗余过滤器语句?

[英]Is there a better way to write redundant filter statements in JavaScript?

I have multiple if statements which I have presented using ternary operator and then for each If a separate filter, This works perfectly fine in React, but the repetition of filter statement makes the code look untidy, id there a way to remove this repetition?我有多个 if 语句,我使用三元运算符呈现,然后为每个 If 一个单独的过滤器,这在 React 中工作得很好,但是过滤器语句的重复使代码看起来不整洁,有没有办法消除这种重复?

let ar = data;
id === 'A' ? ar = ar.filter(item => item > 4) : Id === 'B' ? ar = ar.filter(item => item > 4 
&& item < 8) : Id === 'C' ? ar = ar.filter(item => item >8 && item < 15) : ar = data;

You can create a function that will return the filter function, like:您可以创建一个 function,它将返回过滤器 function,例如:

function makeFilterFn(id){
  switch (id){
      case 'A':
        return item => item > 4
      case 'B':
        return item => item > 4 && item < 8
      case 'C':
        return item => item > 8 && item < 15
      default:
        return null
  }
}

const filterFn = makeFilterFn(id)

const result = filterFn ? ar.filter(filterFn) : ar

 const ar = [1,2,3,4,5,6,7,8,9,10]; const id = "A"; const filtered = { "A": ar.filter(item => item > 4), "B": ar.filter(item => item > 4 && item < 8), "C": ar.filter(item => item >8 && item < 15) }[id] console.log(filtered)

Let's run through some refactoring and see what we can improve.让我们进行一些重构,看看我们可以改进什么。 First I'll split it across multiple lines just so that I can see it easier:首先,我将它分成多行,以便我可以更容易地看到它:

let ar = data;
id === 'A' ?
  ar = ar.filter(item => item > 4) : 
id === 'B' ? 
  ar = ar.filter(item => item > 4 && item < 8) : 
id === 'C' ? 
  ar = ar.filter(item => item > 8 && item < 15) :
//default
ar = data;

First thing I notice is that you are assigning multiple times, but using a ternary, which makes that unneeded.我注意到的第一件事是您分配了多次,但使用了三元组,这使得它不需要。 Let's fix that:让我们解决这个问题:

let ar = data
ar = (
id === 'A' ?
  ar.filter(item => item > 4) : 
id === 'B' ? 
  ar.filter(item => item > 4 && item < 8) : 
id === 'C' ? 
  ar.filter(item => item > 8 && item < 15) :
//default
data
)

Next, ar.filter is getting called every time (except for the default case), and only the arguments are changing.接下来,每次都会调用ar.filter (默认情况除外),并且只有 arguments 发生变化。 The default case can be changed to be a filter that returns everything so that it is more consistent, and then we can extract the arguments to a variable (let's call it filter ):可以将默认情况更改为返回所有内容的过滤器,使其更加一致,然后我们可以将 arguments 提取到变量中(我们称之为filter ):

let ar = data
// we are just determining the argument here
let filter = ( 
id === 'A' ?
  item => item > 4 : 
id === 'B' ? 
  item => item > 4 && item < 8 : 
id === 'C' ? 
  item => item > 8 && item < 15 :
// default is to return all items
item => true
)

// now we can use the argument in the function call
ar = ar.filter(filter)

That removes most of the duplication here, but we are comparing to id in the same way multiple times.这消除了这里的大部分重复,但我们多次以相同的方式与id进行比较。 Like Pavlos mentioned, if you want to pick an option based on a string id, basic objects can let you do that.就像Pavlos提到的,如果您想根据字符串 id 选择一个选项,基本对象可以让您这样做。 The problem is we loose our default argument, but we can usually use the ||问题是我们失去了默认参数,但我们通常可以使用|| ("or") operator to fix that: ("or") 运算符来解决这个问题:

let ar = data

// another benefit of doing it this way is that it is super easy to add 
// new filters now, and you can even pass this in as a prop to your component.
let filters = { 
  'A' : item => item > 4, 
  'B' : item => item > 4 && item < 8,
  'C' : item => item >8 && item < 15
}
let defaultFilter = item => true 

// pick the right filter
let filter = filters[id] || defaultFilter

// now filter the collection with that filter
ar = ar.filter(filter)

With this, you've turned an imperative process of picking the right filter into a declarative process.有了这个,您已经将选择正确过滤器的命令式过程转变为声明性过程。 The filters object now lists the filters without any logic. filters object 现在列出没有任何逻辑的过滤器。 This is much more flexible and allows for more future refactoring in other parts of the codebase.这更加灵活,并允许在代码库的其他部分进行更多的重构。

One other tip that might help would be rearrange the argument so that item is in the middle, and the numbers go from smallest to largest:另一个可能有用的提示是重新排列参数,使item位于中间,数字 go 从最小到最大:

item => 4 < item && item < 8

(See this answer for more) (有关更多信息,请参阅此答案

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

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