推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
autoxbc

偶得一法跳出数组循环

  •  
  •   autoxbc · Dec 31, 2018 · 5557 views
    This topic created in 2712 days ago, the information mentioned may be changed or developed.

    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)仍然有效,显然比抛出错误法好多了

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

    Supplement 1  ·  Jan 1, 2019
    16 replies    2019-01-25 09:01:23 +08:00
    autoxbc
        1
    autoxbc  
    OP
       Dec 31, 2018
    改进一下例子
    ```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;
    }
    })
    ```
    kx5d62Jn1J9MjoXP
        2
    kx5d62Jn1J9MjoXP  
       Dec 31, 2018 via Android   ❤️ 1
    学点函数式编程就知道你这做法不好了
    要达到你这效果,简单的做法是先 take until > 3, 然后该干嘛干嘛
    lastpass
        3
    lastpass  
       Dec 31, 2018 via Android
    system.exot()
    lastpass
        4
    lastpass  
       Dec 31, 2018 via Android
    o --> i
    congeec
        5
    congeec  
       Dec 31, 2018 via iPhone
    二楼说得对,你需要 takewhile 函数
    will0404
        6
    will0404  
       Dec 31, 2018 via Android
    这些方法不应该有 side effort。
    will0404
        7
    will0404  
       Dec 31, 2018 via Android
    effort -> effect
    zealot0630
        8
    zealot0630  
       Dec 31, 2018   ❤️ 1
    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
        9
    zealot0630  
       Dec 31, 2018   ❤️ 1
    JS 的 iterator 是 mutable 的,简直反设计,下面是个能跑的实现和例子

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

    第一个参数 p 决定什么时候跳出来,楼主按照需求实现 p 函数就可以了
    Justin13
        10
    Justin13  
       Jan 1, 2019 via Android
    乱改属性可是大忌。可以学学 haskell
    msg7086
        11
    msg7086  
       Jan 1, 2019
    没过几个月,楼主就被后来接手的程序员打死了。
    lihongjie0209
        12
    lihongjie0209  
       Jan 1, 2019
    瞎搞
    plqws
        13
    plqws  
       Jan 1, 2019   ❤️ 1
    在操作前先 slice 不好吗
    tinywhale
        14
    tinywhale  
       Jan 1, 2019
    我觉得你想要的效果是 elixir 里的 `Enum.reduce_while/3`,我偶尔也觉得 js array 应该有个类似的,后来觉得如果要这样的效果还不如直接 for loop
    codeduan
        15
    codeduan  
       Jan 2, 2019
    一般来说用 some 已经够了,不行的话就用 for loop 吧。
    ghostheaven
        16
    ghostheaven  
       Jan 25, 2019 via Android
    用 generator 重新实现那几个函数,自己定义一个用于结束的 Symbol,当 yield 这个 Symbol 的时候循环结束,并返回默认值
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   5370 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 55ms · UTC 08:46 · PVG 16:46 · LAX 01:46 · JFK 04:46
    ♥ Do have faith in what you're doing.