在与正则表达式匹配的元素处拆分数组

时间:2016-06-01 02:10:18

标签: javascript arrays regex split

我有一个像:

这样的数组
var a= ['--test--','some','someOther','--ts','som','someOthe','--t','so','someOth']

我想把它分成3个数组,即

['--test--','some','someOther']
['--ts','som','someOthe']
['--t','so','someOth']

所以基本上我想把它拆分到匹配条件str.indexOf('--') > -1

的元素

最有效的方法是什么?

P.S:我用一个巨大的代码和奇怪的逻辑完成了它,但我正在寻找一种干净的方法来做到这一点。

5 个答案:

答案 0 :(得分:1)

这是一个基于生成器的解决方案,有点让人联想到@ anubhava的:

function *partition(array) {
  let tmp = [], i = 0;

  for (const e of array) {
    if (i++ && e.indexOf('--') >= 0) yield tmp, tmp = []; 
    tmp.push(e);
  }

  yield tmp;
}

console.log(...partition(['--test--','some','someOther','--ts','som','someOthe','--t','so','someOth']));

我们还可以通过传递函数来概括新桶应该开始的逻辑:

function makePartitioner(startNew) {
  return function *(array) {
    let tmp = [], i = 0;

    for (const e of array) {
      if (i++ && startNew(e)) yield tmp, tmp = [];
      tmp.push(e);
    }

    yield tmp;
  };
}

var partitioner = makePartitioner(e => e.indexOf('--') >= 0);
console.log(...partitioner(['--a, 'b', '--c']));

发电机方法的优点是:

  1. 您可以传入任何可迭代的内容,而不仅仅是数组。
  2. 它可以处理输入流,甚至是无限输入。

答案 1 :(得分:0)

我使用forEach

提出了这个问题



var a= ['--test--','some','someOther','--ts','som','someOthe','--t','so','someOth']
    
var arr=[];
var tmp=[];
    
a.forEach(function(e) {
   if (e.indexOf('--') == 0) {
      if (tmp.length>0)
         arr.push(tmp)
      tmp=[]
   }
   tmp.push(e);
});
arr.push(tmp);

document.writeln('<pre>' + arr.join('\n') + '</pre>');
&#13;
&#13;
&#13;

答案 2 :(得分:0)

功能性解决方案:

&#13;
&#13;
var a = ['--test--', 'some', 'someOther', '--ts', 'som', 'someOthe', '--t', 'so', 'someOth'];

function split(array, pattern) {
  return array.reduce(function(result, element, index) {
    if (pattern.test(element) && index) {
      result.push([element]);
    } else {
      result[result.length - 1].push(element);
    }
    return result;
  }, [[]]);
}

console.log(split(a, /--/));
console.log(split([], /--/));
console.log(split(['some', '--test--'], /--/));
&#13;
&#13;
&#13;

受@seahorsepop启发的另一种非功能性解决方案:

function split(array, pattern) {
  var result = [], prev = 0, length = array.length;
  for (var i = 1; i < length; ++i) {
    if (pattern.test(array[i])) {
      result.push(array.slice(prev, i));
      prev = i;
    }
  }
  result.push(array.slice(prev, length));
  return result;
}

对于一个聪明的基于发电机的解决方案,请参阅@ torazaburo的答案。

效果比较:

  1. 功能:10.7秒/ 1000000次迭代/ Chrome 48
  2. For-loop:10.5秒/ 1000000次迭代/ Chrome 48
  3. 生成器:50秒/ 1000000次迭代/ Chrome 48
  4. 我建议使用功能性或循环式方法,具体取决于您的偏好。

答案 3 :(得分:-1)

@le_m发布了这个代码的更好的推广。

var a = ['--test--', 'some', 'someOther', '--ts', 'som', 'someOthe', '--t', 'so', 'someOth']

var result = a.reduce((prev, curr, idx) => {
  if (!idx || curr.startsWith("--")) {
    prev.push([curr])
  } else {
    prev.push(prev.pop().concat(curr))
  }
  return prev;
}, [])

console.log(result)

答案 4 :(得分:-1)

修改了原始代码,因为它在所有情况下都不起作用。

Edit2:回到单个for循环:P

function split(array, pattern) {
    var result = [];
    for (var x = 0, y = 0; x <= array.length; x++) {
        if((x < array.length ? array[x].indexOf(pattern) > -1 : true) && x > y) {
            result.push(a.slice(y, x));
            y = x;
        }
    }
    return result;
}

var a = ["tes--t", "some", "someOther", "--ts", "som", "someOthe", "--t", "so", "someOth--"];

console.log(split(a, "--"));