代码之家  ›  专栏  ›  技术社区  ›  chrisl-921fb74d

函数编程javascript链过滤器操作默认值

  •  1
  • chrisl-921fb74d  · 技术社区  · 6 年前

    有没有一种方法可以过滤一个数组,如果它没有返回默认为单个链中默认选项的对象?

    例如

    [1,2,3]
        .filter(isDivisibleByTen)
        // otherwise return whatever
    

    我可以这样写

    const result [1,2,3].filter(isDivisibleByTen) 
    result ? result [0]
    
    4 回复  |  直到 6 年前
        1
  •  1
  •   Finesse    6 年前

    解决方案1。没有副作用。

    也许吧 reduce 是唯一提供数组并可以返回任意值的数组方法,因此可以使用它:

    [1,2,3]
        .filter(isDivisibleByTen)
        .reduce((_1, _2, _3, array) => array, 'defaultValue');
    

    这个解决方案是一个位处理器时间浪费(在数组上循环而没有好处),但是它可以很容易地与任何链结合。

    解决方案2。优雅的那个。

    可以将自定义方法添加到数组原型中,以使其在链中可用:

    Array.prototype.filledOrDefault = function(defaultValue) {
        return this.length ? this : defaultValue;
    }
    
    [1,2,3]
        .filter(isDivisibleByTen)
        .filledOrDefault('defaultValue');
    

    不建议使用此解决方案,因为它会修改全局值( Array )它被页面上的其他脚本使用。

        2
  •  1
  •   zer00ne    6 年前

    这是我认为您在一行中要查找的内容,但是如果结果为假,filter()将不返回任何内容。在演示1中 filter() 使用。在演示2中 map() 与返回的任意值一起使用 "default" 作为备用返回。


    演示1


    console.log([1, 21, 30].filter(a => a % 10 === 0));

    演示2


    console.log([1,21,30].map(a => a % 10 === 0 ? a : 'default'));
        3
  •  1
  •   Nick    6 年前

    你可以试试 reduce() . 这允许您传递一个初始值(默认返回值),然后在返回数组通过测试时向其添加值。因此,如果没有值通过测试,函数将返回默认值。

    console.log([1,21,30].reduce((t, v) => { return v % 10 === 0 ? (t = 'default' ? [v] : t.concat(v)) : t; }, 'default'))

        console.log([1,21,35].reduce((t, v) => { return v % 10 === 0 ? (t = 'default' ? [v] : t.concat(v)) : t; }, 'default'))
        4
  •  0
  •   intentionally-left-nil    6 年前

    我将在这里添加一个更详细的选项。此解决方案使用3个纯函数,然后将其组合到管道中。这是典型的函数式编程,并且有一个附带的好处,那就是能够独立地测试函数,以确保它们完全满足您的需要。

    (作为侧边栏,其他语言(如elixir)使链接在语法上更令人愉快,但我离题了)

    const defaultValue = "foobar";
    
    const isDivisibleBy10 = n => n % 10 === 0;
    
    const enforceDefault = numbers => numbers.length ? numbers : [defaultValue];
    
    const unpackSingleton = numbers => numbers.length === 1 ? numbers[0] : numbers;
    
    
    const pipeline = numbers =>
      unpackSingleton(
        enforceDefault(
          numbers.filter(isDivisibleBy10)
        )
      )
    
    console.log(pipeline([2])); // no matches so returns default
    console.log(pipeline([20])) // one match so returns the item
    
    console.log(pipeline([1, 20, 10, 3])) // general case