【问题标题】:How to dynamically split an array?如何动态拆分数组?
【发布时间】:2019-02-02 16:52:22
【问题描述】:

我有一个字符串数组,有点像这样:

["x", "foo", "y", "bar", "baz", "z", "0"]

我需要为每个 X、Y 和 Z 或其他特殊关键字拆分数组。

我尝试使用[x,y,z].split(y) 拆分数组,但我很确定split() 仅用于字符串。

关键字(xyz ) 必须是数组中的第一个。 我该怎么做?

这就是我想要得到的:

[
    ["x", "foo"],
    ["y", "bar", "baz"],
    ["z", "0"]
]

【问题讨论】:

  • 你有一组键,还是一个数组,哪个顺序很重要?
  • @DexieTheSheep 数组的顺序重要吗(x,y,z) 重要吗?
  • 顺序很重要。这用于我正在研究的语言的解释器,因此通常输入内容的顺序很重要。
  • 您编写自己的词法分析器有什么特别的原因吗?它可能是大多数语言中最不有趣的部分,因此您可能只想使用已经可用的一种。

标签: javascript arrays split


【解决方案1】:

您可以在键字符串的索引上使用一个数组和一个闭包,如果找到一个键,则推送一个空数组。

var array = ["x", "foo", "y", "bar", "baz", "z", "0"],
    keys = ["x", "y", "z"],
    result = array.reduce((i => (r, s) => {
        if (s === keys[i]) {
            r.push([]);
            i++;
        }
        r[r.length - 1].push(s);
        return r;
    })(0), []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

  • 我不认为 OP 需要 keys 才能按顺序出现,是吗?即使他们这样做了,关闭也非常令人困惑。要么将 i 变量放在外部作用域中,要么如果您喜欢函数式编程,请将其线程化到累加器中。
  • @Bergi,正如一条评论所示,op 按顺序需要密钥。
  • 我以为是指结果数组的顺序,即属性concat(result) == input 成立。
【解决方案2】:
 const keywords = new Set(["x", "y", "z"]);

 let acc = [];
 const result = [];

 for(const el of array) {
   if(keywords.has(el)) {
     result.push(acc = [el]);
   } else acc.push(el);
 }

【讨论】:

    【解决方案3】:

    我为时已晚,但我将展示与其他答案完全不同的方法。在这种方法中,输入数组使用join() 转换为字符串,结果主要使用正则表达式和split() 方法获得:

    const input = ["x", "foo", "y", "bar", "baz", "z", "0"];
    const keyRegex = /(?=#x#)|(?=#y#)|(?=#z#)/;
    
    let res = ("#" + input.join("#") + "#")          // #x#foo#y#bar#baz#z#0#"
        .split(keyRegex)                             // [#x#foo, #y#bar#baz, #z#0#]
        .map(str => str.split("#").filter(Boolean));
    
    console.log(JSON.stringify(res));

    这是另一种方法,使用map() 覆盖带有keys 的数组。注意我已将input 数组的副本传递给map 方法,并将其用作this 参数。另外,我使用splice() over this 来删除已经分析的部分并在缩短的数组上执行期货findIndex()。但是,没有什么比在输入数组上使用 reduce() 或标准 loop 的解决方案更好。

    const input = ["x", "foo", "y", "bar", "baz", "z", "0"];
    const keys = ["x", "y", "z"];
    
    let res = keys.map(function(k, i)
    {
        let a = this.findIndex(x => x === k);
        let b = this.findIndex(x => x === keys[i+1]);
        return this.splice(a, b >= 0 ? b : this.length);
    }, input.slice());
    
    console.log(JSON.stringify(res));

    【讨论】:

      【解决方案4】:

      只是另一种方法。你可以使用slice

      var a = ["x", "foo", "y", "bar", "baz", "z", "0"];
      var breakpoints = ['x', 'y', 'z'];
      var res = [];
      for(var i = 0; i < breakpoints.length - 1; i++) {
        res = res.concat([a.slice(a.indexOf(breakpoints[i]), a.indexOf(breakpoints[i+1]))]);
      }
      res = res.concat([a.slice(a.indexOf(breakpoints[i]))]);
      console.log(res);

      【讨论】:

        【解决方案5】:

        如果有帮助的话,只是已经发布的好答案的简短替代方案。

        这是使用Array.reduce:

        const input = ['x', 'foo', 'y', 'bar', 'baz', 'z', '0'];
        const keywords = ['x', 'y', 'z'];
        
        const result = input.reduce((result, value) => {
          keywords.includes(value) ? result.push([value]) : result[result.length - 1].push(value);
          return result;
        }, []);
        
        console.log(result);

        请注意,如果输入数组中的第一项不是关键字(不应该是关键字),它将失败。否则,您可以轻松地将条件更改为 keywords.includes(value) || keywords.length === 0

        【讨论】:

          【解决方案6】:

          可以在第一阶段使用双重归约计算每个键的索引,并在第二阶段对数组进行拆分:

          var arr = ["x", "foo", "y", "bar", "baz", "z", "0"];
          var keys = keys = ["x", "y", "z"];
          
          var retVal = arr.reduce(function(acc, ele, idx) {
              if (keys.indexOf(ele) > -1) {
                  acc.push(idx);
              }
              return acc;
          }, []).reduce(function(acc, ele, idx, a) {
              acc.push(arr.slice(ele, a[idx+1]));
              return acc;
          }, []);
          
          console.log(retVal);

          【讨论】:

            【解决方案7】:

            您可以使用slice 通过给定键的索引提取单个数组并将其推送到最终数组中。

            const arr = ["x", "foo", "y", "bar", "baz", "z", "0"];
            function splitByKeys(...keys){
            let splitarr = [];
              for(let i =0; i<keys.length;i++){
               if(i == keys.length -1 ){
                 splitarr.push(arr.slice( arr.indexOf(keys[i]) , arr.length));
               }else{
                splitarr.push(arr.slice( arr.indexOf(keys[i]) , arr.indexOf(keys[i+1])));
               }
              }
              return splitarr;
            }
            console.log(splitByKeys("x", "y", "z"));

            【讨论】:

              【解决方案8】:

              您可以通过以下代码做到这一点:

              function separator(a) {
                var result = [];
              
                for (var i = 0; i < a.length; i++) {
                  var index = a[i].trim().toLowerCase();
              
                  switch (index) {
                    case "x":
                    case "y":
                    case "z":
                      if (result[index] == undefined) {
                        result.push([index]);
                      }
                      break;
              
                    default:
                      result[result.length - 1].push(a[i]);
                  }
                }
              
                return result;
              }
              
              // Sample:
              var arr = ["x", "foo", "y", "bar", "baz", "z", "0"];
              console.log(separator(arr));
              
              // Result must be:
              // [["x", "foo"], ["y", "bar", "baz"], ["z", "0"]]
              

              或者用这个来分组:

              function separator(a) {
                var result = {};
                var lastIndex = "";
              
                for (var i = 0; i < a.length; i++) {
                  var index = a[i].trim().toLowerCase();
              
                  switch (index) {
                    case "x":
                    case "y":
                    case "z":
                      if (result[index] == undefined) {
                        result[index] = [];
                      }
                      lastIndex = index;
                      break;
              
                    default:
                      result[lastIndex].push(a[i]);
                  }
                }
              
                return result;
              }
              
              // Sample:
              var arr = ["x", "foo", "y", "bar", "baz", "z", "0"];
              console.log(separator(arr));
              
              // Result must be:
              // {"x": ["foo"], "y": ["bar", "baz"], "z": ["0"]}
              

              第二个代码可以像这样在高级数组上工作:

              ["x", "foo", "y", "bar", "x", "baz", "z", "0", "y", "bar2"]
              
              And result is this:
              {"x": ["foo", "baz"], "y": ["bar", "bar2"], "z": ["0"]}
              

              【讨论】:

                【解决方案9】:
                const input = ['x', 'foo', 'y', 'bar', 'baz', 'z', '0'];
                const keywords = ['x', 'y', 'z'];
                
                input.reduce((prev, val) => {
                    const split = keywords.includes(val);
                    const index = prev.length - Number(!split);
                    prev[index] = split ? [val] : prev[index].concat(val)
                    return prev;
                }, []);
                

                这是一种进行拆分并避免不良副作用的实用方法。

                【讨论】:

                  【解决方案10】:

                  很简单!

                  const arr = ["x", "foo", "y", "bar", "baz", "z", "0"];
                  const specialChar = ['x', 'y', 'z'];
                  let result = [];
                  
                  arr.forEach((el, index) => {
                    if(specialChar.includes(el)){
                      result.push([el, arr[index + 1]])
                    }
                  });
                  
                  console.log(result)

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2021-11-06
                    • 1970-01-01
                    • 2021-03-02
                    • 1970-01-01
                    • 2015-10-11
                    • 1970-01-01
                    • 1970-01-01
                    • 2020-06-09
                    相关资源
                    最近更新 更多