在函数式编程中,基于单个项的特征进行过滤相对简单——例如,过滤以仅查找奇数:
const arrayOfInfo = [1,2,3,4,5,6,8,10,11,13,15,16,17,19]
const onlyOddNumbers = arrayOfInfo.filter(function(item) {
return (item % 2 == 1) ? true : false
})
但是,如果我需要上下文,我不确定惯用的做事方式是什么——换句话说,了解周围的项目。例如,如果我只想过滤两边被奇数包围的项目,我可以这样做(我利用了一些 JavaScript 特性,甚至不想先检查索引是否存在):
const surroundedByOneOddNumber = arrayOfInfo.filter(function(item,index) {
const itemBefore = arrayOfInfo[index - 1]
const itemAfter = arrayOfInfo[index + 1]
return ((itemBefore % 2 == 1) && (itemAfter % 2 == 1)) ? true : false
})
如果我想找到每边被两个奇数包围的数字,这将变得更加明显,因为这是一种有问题或效率低下的代码编写方式:
const surroundedByTwoOddNumbers = arrayOfInfo.filter(function(item,index) {
const itemBefore = arrayOfInfo[index - 1]
const itemTwoBefore = arrayOfInfo[index - 2]
const itemAfter = arrayOfInfo[index + 1]
const itemTwoAfter = arrayOfInfo[index + 2]
return ((itemBefore % 2 == 1) && (itemTwoBefore % 2 == 1) && (itemAfter % 2 == 1) && (itemTwoAfter % 2 == 1)) ? true : false
})
显然,如果我想做一些事情,比如只找到每边 50 个奇数包围的数字,那么编写这样的代码将毫无意义。
有没有用函数式编程解决这个问题的好方法,或者在这种情况下最好降到 for/while 循环样式?
CodePen 与示例一起玩:https ://codepen.io/jnpdx/pen/MvradM
函数式编程的整个思想是编写没有副作用的纯函数
Array.filter
是函数式的,因为它返回一个新数组,而不改变原始数组。您可以在同一个数组上运行该方法数百万次而无需更改它。
如果您的逻辑变得复杂,代码也变得复杂,则没有功能魔法可以解决您的领域问题。
但是,您可以创建一个createFilter
函数,它会根据您的域要求创建过滤器函数,例如:
const createFilter = ({
before = e => true,
after = e => true
}) => (entry, idx, entries) =>
before(entries[idx - 1]) && after(entries[idx + 1]) }; }
// This will return [ 4, 4 ] I guess ;)
[1, 3, 3, 3, 2, 4, 5, 2, 4, 7].filter(createFilter({
before: (e) => e % 2 === 0,
after: (e) => e % 2 === 1,
}))
以同样的方式,您只能获得前项为 50 和 100 后的值:
[50, 1, 100, 4, 50, 3, 100].filter(createFilter({
before: (e) => e === 50,
after: (e) => e === 100
})) // pretty sure the output is [1, 3]
所以这样你就有了一个可重用的filterCreator
,将它扩展到你的需要;)
@Aadit M Shah 是的,在再次阅读 OP 后,我得出的结论是,我的方法仍然有效,您只需要编写自己的filterCreator
函数即可。Array.filter
实际上并没有什么问题。
const filterBySurrounding = (n, meetCondition) => {
return (item, idx, array) => {
return n <= idx && idx + n <= array.length - 1
? array.slice(idx - n, idx).every(meetCondition) &&
array.slice(idx + 1, idx + 1 + n).every(meetCondition)
: false
}
}
const isOdd = n => n % 2 === 1
array.filter(filterBySurrounding(50, isOdd))
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句