【问题标题】:Functional way to Insert a value between all the elements inside an array在数组内的所有元素之间插入值的功能方法
【发布时间】:2019-06-09 10:33:21
【问题描述】:

假设我有以下数组:

const myArray = ["q", "w", "e", "r", "t", "y"]

我想做的是在所有元素之间添加一个元素,如下所示:

myArray.someMethod("XXX")
// ["q", "XXX", "w", "XXX", "e", "XXX", "r", "XXX", "t", "XXX", "y"]

在某种程度上,这有点像 .join 所做的,但我希望输出是另一个数组,而不是字符串。

我知道如何通过循环来做到这一点,但我想知道实现这一点的“功能”方式。

【问题讨论】:

标签: javascript arrays functional-programming


【解决方案1】:

您可以通过获取剩余参数并检查剩余数组的长度来采用递归方法,而不是迭代方法。

const
    zip = ([a, ...r], v) => r.length ? [a, v, ...zip(r, v)] : [a];

console.log(zip(["q", "w", "e", "r", "t", "y"], 'XXX'));
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

    【解决方案2】:

    在函数式编程方式中,Array 是 Monad,这意味着它是 flatMappable。 FlatMap 是 Monadic 绑定运算符的实现,对于 Array,它将元素映射到新数组并将它们展平在一起。

    有了这个想法,你只需要在 flatMap 函数内的输出数组中添加一个新值。见下文

    Array.prototype.someMethod = function(a){ return this.flatMap(i => [i,a]) }
    
    myArray.someMethod("XXX")
    // Array(12) [ "q", "XXX", "w", "XXX", "e", "XXX", "r", "XXX", "t", "XXX", … ]
    

    上面的例子在Array的末尾添加了XXX,所以我们可以通过使用flatMap的index参数来忽略最后一个元素被填充,如下所示

    Array.prototype.someMethod = function(a){ let L=this.length; return this.flatMap((n,i) => (i<L-1) ? [n,a] : [n]) }
    
    myArray.someMethod("XXX")
    // Array(11) [ "q", "XXX", "w", "XXX", "e", "XXX", "r", "XXX", "t", "XXX", "y"]
    

    【讨论】:

    • 这很好,但也会在末尾附加"XXX",不是吗?
    • 哦,那是真的。我现在添加了一条评论 bsz
    • 很高兴看到人们在 Javascript 中使用 monad :D
    【解决方案3】:

    您可以将.map().concat() 一起使用:

    const data = ["q", "w", "e", "r", "t", "y"];
    const str = "XXX";
    
    const insertValue = (arr, val) => [].concat(
        ...arr.map((v, i) => (i > 0 ? [str, v] : v))
    );
    
    console.log(insertValue(data, str));
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

      【解决方案4】:

      const myArray = ["q", "w", "e", "r", "t", "y"]
      const joinStr = 'xxx';
      console.log(myArray.join(','+ joinStr + ',').split(','));

      【讨论】:

      • 如果, 将不起作用 - glue 包含在任何数组元素中。
      • @Tushar 是的,但您可以将其更改为任何独特的"glue", 是我在此示例中使用的,它可能类似于 @%
      • 是的。但是,如果数据来自第三方服务或用户输入,则您无法保证 胶水 的唯一性。
      【解决方案5】:

      你可以使用 map() 和 flat()

      const myArray = ["q", "w", "e", "r", "t", "y"];
      const newArray = myArray.map((i) => {
         return [i, 'xxx']
      }).flat();
      
      console.log(newArray);
      

      【讨论】:

      • 我不知道flat()!这很有帮助。即使解决方案不正确,因为它还会在数组末尾引入“胶水”。
      • 请注意,flat 是一种实验性技术,并非所有浏览器都支持。
      • 希望 babel 能安全转译
      【解决方案6】:

      您可以使用reduce 来转换原始数组,然后将其放入一个有两个参数的函数中,或者将其添加为Array.prototype 的方法(如果您真的想要帖子中的调用方法):

      const myArray = ["q", "w", "e", "r", "t", "y"]
      
      // A function taking array and glue arguments
      
      const interpose = (array, glue) => array.reduce(
         (acc, c,i,a) => (
              acc.push(c) && (i < a.length -1) && acc.push( glue),
              acc
          ), []
      );
      
      // As an array method
      
      Array.prototype.interpose = function( glue) {
          return  this.reduce(
          (acc, c,i,a) => (
               acc.push(c) && (i < a.length -1) && acc.push( glue),
               acc
           ), []);
      }
      
      // Test
      
      console.log( 'interpose( myArray, "XXX" = %s', interpose( myArray, "XXX"));
      console.log( 'myArray.interpose("XXX")  = %s', myArray.interpose("XXX"));

      【讨论】:

        【解决方案7】:

        你可以加入,因为加入的默认字符是逗号,然后用','+glue+','包围每个逗号,最后用逗号分割。

        const myArray = ["q", "w", "e", "r", "t", "y"]
        
        Array.prototype.someMethod = function(glue){
            return this.join().replaceAll(',',','+glue+',').split(',');
        } 
        
        console.log(myArray.someMethod("XXX"))
        // ["q", "XXX", "w", "XXX", "e", "XXX", "r", "XXX", "t", "XXX", "y"]

        【讨论】:

          猜你喜欢
          • 2016-12-12
          • 2016-09-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多