【问题标题】:JavaScript - String.split() but for Arrays?JavaScript - String.split() 但对于数组?
【发布时间】:2019-05-06 14:01:46
【问题描述】:

假设我有这个字符串数组(它们是 HTML 元素,但我们可以使用字符串来保持简单):

["something", "else", "and", "d", "more", "things", "in", "the", "d", "array", "etc"]

我需要一种快速的方法来将此数组拆分为 "d"。有点像String.split(),除了数组。最终结果应该是这样的:

[["something", "else", "and"], ["more", "things", "in", "the"], ["array", "etc"]]

是否有任何简单的单行代码?也许JS内置了一个函数,我只是想念它?

【问题讨论】:

    标签: javascript arrays split data-manipulation


    【解决方案1】:

    如果是你想要的单线,那么你去:

    var myArray = ["something", "else", "and", "d", "more", "things", "in", "the", "d", "array", "etc"];
    
    const result = myArray.reduce((a, c) => c === "d" ? (a.arr[++a.i] = []) && a : a.arr[a.i].push(c) && a, {arr: [[]], i: 0}).arr;
    
    console.log(result);

    【讨论】:

    • 是的,这是一个单线;)呵呵。我猜 OP 正在寻找一种本地方法(不同版本的 split)或用于数组分箱的方法,给定一个分隔符。
    • @vol7ron Ye 我也这么认为。虽然不幸的是没有,所以如果你想要一个单线,就必须这样做哈哈
    【解决方案2】:

    一种选择是用空格连接,然后用' d ' 分割,然后用空格分割每个子数组:

    const input = ["something", "else", "and", "d", "more", "things", "in", "the", "d", "array", "etc"];
    const output = input
      .join(' ')
      .split(' d ')
      .map(str => str.split(' '));
    console.log(output);

    或者,在不加入的情况下,找出每个dsliceds 周围输入的每个部分的索引:

    const input = ["something", "else", "and", "d", "more", "things", "in", "the", "d", "array", "etc"];
    const dIndicies = input.reduce((a, item, i) => {
      if (item === 'd') a.push(i);
      return a;
    }, []);
    const output = dIndicies.reduce((a, dIndex, i, arr) => {
      const nextDIndex = arr[i + 1];
      a.push(input.slice(dIndex + 1, nextDIndex));
      return a;
    }, [input.slice(0, dIndicies[0] - 1)]);
    console.log(output);

    【讨论】:

    • 不错的解决方案。我希望 OP 不打算在任何字符串中有空格... :)
    【解决方案3】:

    let myArray = ["something", "else", "and", "d", "more", "things", "in", "the", "d", "array", "etc"];
    let splitArray = [],
        tempArray = [];
    myArray.forEach((ele, index) => {
        if(ele !== 'd') {
          tempArray.push(ele);
        }
        if(ele === 'd' || index === myArray.length - 1) {
          splitArray.push(tempArray);
          tempArray = []; 
        }
    })
    
    console.log(': ', splitArray);

    【讨论】:

      【解决方案4】:

      一个简单的forEach 方法就足够了。

      var arr = ["something", "else", "and", "d", "more", "things", "in", "the", "d", "array", "etc"];
      var result = [], temp = [];
      
      arr.forEach(function(elem, index){
          elem !=='d' ? temp.push(elem) : (result.push(temp), temp = []);
          index==arr.length-1 && (result.push(temp));
      });
      
      console.log(result)

      【讨论】:

        【解决方案5】:

        为了回答您的问题,没有想到任何简洁的单行代码,但是您可以通过迭代您的值并且如果单词不是 @987654321 只需几行代码即可完成您想要的@存储它;如果是,则创建一个新数组来保存下一个非“d”值:

        const words = ["something", "else", "and", "d", "more", "things", "in", "the", "d", "array", "etc"]
        
        let grouped = words.reduce((response,word)=>{
          if (word!=='d')
            response[response.length-1].push(word)
          else
            response[response.length]=[]
          return response
        },[[]])
        
        console.log(grouped)

        【讨论】:

        • 为此提供了单线解决方案。它像疯了一样难以阅读,但它有效,哈哈
        【解决方案6】:

        使用 reduce 从一个累加器开始,该累加器有一个包含空数组的数组。如果当前项是拆分值,则在末尾添加一个额外的空数组,否则将最后一个数组与当前项展开。

        const arr = ["something", "else", "and", "d", "more", "things", "in", "the", "d", "array", "etc"];
        
        const splitArray = (array, val) =>
          array && array.length
            ? array.reduce(
                (results, item) =>
                  item === val
                    ? [...results, []]
                    : [...results.filter((_, i) => i < results.length - 1), [...results[results.length - 1], item]],
                [[]]
              )
            : array;
          
          
        console.log(splitArray(arr, 'd'));

        【讨论】:

        • 如果数组以“d”开头或结尾有点奇怪。
        • 不是真的,它的工作原理与字符串拆分相同,因为 ',abc'.split(',') 将给出 ['', 'abc'] 所以我很高兴它给出一个空数组如果数组以拆分值开头。
        【解决方案7】:

        您可以使用以下代码创建一个非常优雅的递归函数:

        let arr = ["something", "else", "and", "d", "more", "things", "in", "the", "d", "array", "etc"]
        
        const spliton = (v, arr, i = arr.indexOf(v)) => (i < 0) 
            ? [arr]
            : [arr.slice(0, i), ...spliton(v, arr.slice(i+1))]
        
        
        console.log(spliton('d', arr))

        【讨论】:

        • 老实说,OP 应该从我的答案中删除已接受的标记,并将其设为已接受的答案。从技术上讲,它是一种可重复使用的单行代码,而且可读性也更高! +1
        【解决方案8】:

        这是适用于任何iterable 输入(包括数组)的函数式编码

        const None =
          Symbol ()
        
        const prepend = (xs, x) =>
         [ x ] .concat (xs)
        
        const split = (f, [ x = None, ...xs ], then = prepend) =>
          x === None
            ? then ([], [])
            : split
                ( f
                , xs
                , (l, r) =>
                    f (x)
                      ? then (prepend (l, r), [])
                      : then (l, prepend (r, x))
                )
        
        const data = 
          [ 'something', 'else', 'and', 'd', 'more', 'things', 'in', 'the', 'd', 'array', 'etc' ]
        
        console .log
          ( split (x => x === 'd', data)
          )
        
        // [ [ 'something', 'else', 'and' ]
        // , [ 'more', 'things', 'in', 'the' ]
        // , [ 'array', 'etc' ]
        // ]

        以及适用于任何array-like 输入的优化

        const prepend = (xs, x) =>
         [ x ] .concat (xs)
        
        const split = (f, xs = [], i = 0, then = prepend) =>
          i >= xs.length
            ? then ([], [])
            : split
                ( f
                , xs
                , i + 1
                , (l, r) =>
                    f (xs[i])
                      ? then (prepend (l, r), [])
                      : then (l, prepend (r, xs[i]))
                )
        
        const data = 
          [ 'something', 'else', 'and', 'd', 'more', 'things', 'in', 'the', 'd', 'array', 'etc' ]
        
        console .log
          ( split (x => x === 'd', data)
          )
        
        // [ [ 'something', 'else', 'and' ]
        // , [ 'more', 'things', 'in', 'the' ]
        // , [ 'array', 'etc' ]
        // ]
        

        两种实现都是O(n)

        【讨论】:

          【解决方案9】:

          如果您不关心 mutating 数组,这对于 whileArray.shift 来说也很简单:

          let r = [[]], data = ["something", "else", "and", "d", "more", "things", "in", "the", "d", "array", "etc"]
          
          while(data.length) {
            let item = data.shift()
            item != 'd' ? r[r.length-1].push(item) : r.push([]) 
          }
          
          console.log(r)

          如果你这样做,那么Array.reduce 会更短:

          let arr = ["something", "else", "and", "d", "more", "things", "in", "the", "d", "array", "etc"]
          
          let f = arr.reduce((r,c) => (c!='d' ? r[r.length-1].push(c) : r.push([]),r),[[]])
          
          console.log(f)

          两者的想法都是从[[]] 开始,然后您需要的唯一检查是迭代的当前元素是否为d,如果是,则推送新数组或推送到r[r.length-1],即前一个@ 987654331@.

          【讨论】:

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