偶得一法跳出数组循环

2018-12-31 21:04:27 +08:00
 autoxbc

some 和 every 可以用 return 值跳出循环

forEach,filter,find,findIndex,map,reduce,reduceRight 没有可用的跳出方法,continue 和 break 都不能用,那么怎么跳出这些数组循环?

网上搜索了一下,只见到一种构造 try catch 结构然后 throw 的方法,一点也不优雅

用于循环的数组自身消失的话,循环不就自然中止了

[1,2,3,4,5].forEach( (val,idx,arr) => {
    if( val > 3 )
        return arr.length = 0 ;
    console.log(val);
} );

跳出过程并未本质改变这些循环的语义,所有的返回值(比如 reduce)仍然有效,显然比抛出错误法好多了

唯一需要注意的是,因为置空的副作用,部分情况要先对数组做浅拷贝

4871 次点击
所在节点    JavaScript
16 条回复
autoxbc
2018-12-31 21:26:37 +08:00
改进一下例子
```js
[1, 2, 3, 4, 5].forEach((val, idx, arr) => {
if (val < 3){
console.log(`${val} < 3`);
}
else {
console.log(`${val} >= 3`);
arr.length = 0;
}
})
```
ssynhtn
2018-12-31 22:04:30 +08:00
学点函数式编程就知道你这做法不好了
要达到你这效果,简单的做法是先 take until > 3, 然后该干嘛干嘛
lastpass
2018-12-31 22:25:45 +08:00
system.exot()
lastpass
2018-12-31 22:26:20 +08:00
o --> i
congeec
2018-12-31 22:31:17 +08:00
二楼说得对,你需要 takewhile 函数
will0404
2018-12-31 22:31:37 +08:00
这些方法不应该有 side effort。
will0404
2018-12-31 22:32:51 +08:00
effort -> effect
zealot0630
2018-12-31 23:02:05 +08:00
unfold 可以,然而这个函数太难驾驭,大部分库和语言都不支持。

https://srfi.schemers.org/srfi-1/srfi-1.html#FoldUnfoldMap


随便写了个 js 实现:

···
function unfold(p, f, g, seed, reduce, tailgen) {
function recursive(iter) {
if (p(iter)) return tailgen(iter);
return reduce(f(iter), recursive(g(iter)));
}

return recursive(seed);
}
···

举一个简单的例子,比如说把一个数组累加起来:

···
sum(a) = unfold(
(e) => !e /* 没有元素时候终止 */,
identify /* identify 函数,返回元素本身 */,
(iter) => iter.nex() /* generator,如何遍历元素 */
a[@@iterator]() /* 种子,数组的迭代器 */
(head, tail) => head + tail /* reduce,如何汇总 */
(e) => 0 /* 如何处理尾巴,也可以理解为初始值 */
)
```

unfold 功能相当强大,你要问有多强大,他是其他所有容器函数( forEach,filter,find,findIndex,map,reduce,reduceRight )的母亲,这些函数都能用一个 unfold 调用,在一行里面实现。
zealot0630
2018-12-31 23:25:34 +08:00
JS 的 iterator 是 mutable 的,简直反设计,下面是个能跑的实现和例子

https://gist.github.com/kghost/b001d39b6c6b541a289774bf137f2da8

第一个参数 p 决定什么时候跳出来,楼主按照需求实现 p 函数就可以了
Justin13
2019-01-01 09:00:12 +08:00
乱改属性可是大忌。可以学学 haskell
msg7086
2019-01-01 09:37:12 +08:00
没过几个月,楼主就被后来接手的程序员打死了。
lihongjie0209
2019-01-01 09:45:23 +08:00
瞎搞
plqws
2019-01-01 09:51:52 +08:00
在操作前先 slice 不好吗
tinywhale
2019-01-01 12:35:03 +08:00
我觉得你想要的效果是 elixir 里的 `Enum.reduce_while/3`,我偶尔也觉得 js array 应该有个类似的,后来觉得如果要这样的效果还不如直接 for loop
codeduan
2019-01-02 10:32:20 +08:00
一般来说用 some 已经够了,不行的话就用 for loop 吧。
ghostheaven
2019-01-25 09:01:23 +08:00
用 generator 重新实现那几个函数,自己定义一个用于结束的 Symbol,当 yield 这个 Symbol 的时候循环结束,并返回默认值

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/522775

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX