如何将 PHP 的 explode(';',$s,3) 匹配到 JavaScript 中的 s.split(';',3)?

How to match PHP's explode(';',$s,3) to s.split(';',3) in JavaScript?

如果您在 PHP 中 运行 一个 explode 并且结果数组长度有限,它将把字符串的剩余部分附加到最后一个元素。这就是分解字符串的行为方式,因为我在拆分中的任何地方都没有说我想 丢弃 我的数据,只是拆分它。这是它在 PHP:

中的工作方式
# Name;Date;Quote
$s = 'Mark Twain;1879-11-14;"We haven\'t all had the good fortune to be ladies; we haven\'t all been generals, or poets, or statesmen; but when the toast works down to the babies, we stand on common ground."';
$a = explode(';',$s,3);
var_dump($a);

array(3) {
  [0]=>
  string(10) "Mark Twain"
  [1]=>
  string(10) "1879-11-14"
  [2]=>
  string(177) ""We haven't all had the good fortune to be ladies; we haven't all been generals, or poets, or statesmen; but when the toast works down to the babies, we stand on common ground.""
}

但是,如果您 运行 JavaScript 中的相同代码:

> var s = 'Mark Twain;1879-11-14;"We haven\'t all had the good fortune to be ladies; we haven\'t all been generals, or poets, or statesmen; but when the toast works down to the babies, we stand on common ground."'
undefined
> var a = s.split(';',3);
undefined
> a
[ 'Mark Twain',
  '1879-11-14',
  '"We haven\'t all had the good fortune to be ladies' ]

这完全没有意义,因为拆分字符串的全部意义在于将字符串的最后部分视为文字,而不是定界。 JavaScript 的 split 与限制完全相同:

# In PHP
$a = array_slice(explode(';',$s), 0, 3);
# Or in JavaScript
var a = s.split(';').slice(0, 3);

如果JavaScript中的用户只想使用这个数组的前两个元素,那么数组是否拆分并不重要。无论如何,前两个元素将始终具有相同的值。唯一改变的元素是拆分数组的最后一个元素。

如果 JavaScript 中带有 limit 方法的原生 split 可以使用 slice 复制,那么它提供什么价值?

但我离题了,在 PHP 中复制 explode 功能的最有效方法是什么?将每个元素作为子字符串删除,直到到达最后一个元素,拆分整个字符串,然后连接剩余的元素,获取 n - 1 分隔符的位置并获取它的子字符串,或者我没有想到的任何其他解决方案?

Loctus.io 为您服务,他们将 php 的 explode 和大量其他 php 功能移植到 javascript

用法:

$s = 'Mark Twain;1879-11-14;"We haven\'t all had the good fortune to be ladies; we haven\'t all been generals, or poets, or statesmen; but when the toast works down to the babies, we stand on common ground."';
"Mark Twain;1879-11-14;"We haven't all had the good fortune to be ladies; we haven't all been generals, or poets, or statesmen; but when the toast works down to the babies, we stand on common ground.""
$a = explode(';',$s,3);

Chrome 的 javascript 控制台报告的 $a 内容:

0: "Mark Twain"
1: "1879-11-14"
2: ""We haven't all had the good fortune to be ladies; we haven't all been generals, or poets, or statesmen; but when the toast works down to the babies, we stand on common ground.""
length: 3

,来源:http://locutus.io/php/strings/explode/

function explode (delimiter, string, limit) {
  //  discuss at: http://locutus.io/php/explode/
  // original by: Kevin van Zonneveld (http://kvz.io)
  //   example 1: explode(' ', 'Kevin van Zonneveld')
  //   returns 1: [ 'Kevin', 'van', 'Zonneveld' ]

  if (arguments.length < 2 ||
    typeof delimiter === 'undefined' ||
    typeof string === 'undefined') {
    return null
  }
  if (delimiter === '' ||
    delimiter === false ||
    delimiter === null) {
    return false
  }
  if (typeof delimiter === 'function' ||
    typeof delimiter === 'object' ||
    typeof string === 'function' ||
    typeof string === 'object') {
    return {
      0: ''
    }
  }
  if (delimiter === true) {
    delimiter = '1'
  }

  // Here we go...
  delimiter += ''
  string += ''

  var s = string.split(delimiter)

  if (typeof limit === 'undefined') return s

  // Support for limit
  if (limit === 0) limit = 1

  // Positive limit
  if (limit > 0) {
    if (limit >= s.length) {
      return s
    }
    return s
      .slice(0, limit - 1)
      .concat([s.slice(limit - 1)
        .join(delimiter)
      ])
  }

  // Negative limit
  if (-limit >= s.length) {
    return []
  }

  s.splice(s.length + limit)
  return s
}

编辑:如果您出于某种原因 need/want 一个较小的实现,这是我针对评论所做的 1:

function explode(delimiter, string, limit) {
    var spl = string.split(delimiter);
    if (spl.length <= limit) {
        return spl;
    }
    var ret = [],i=0;
    for (; i < limit; ++i) {
        ret.push(spl[i]);
    }
    for (; i < spl.length; ++i) {
        ret[limit - 1] += delimiter+spl[i];
    }
    return ret;
}

根据文档,split 函数接受两个参数:

string.split(separator, limit)

然而,这仍然不是您想要的结果,因为:

The second parameter is an integer that specifies the number of splits, items after the split limit will not be included in the array

但是,我注意到 ';'文中后面有一个space。所以你可以使用正则表达式。

var s = 'Mark Twain;1879-11-14;"We haven\'t all had the good fortune to be ladies; we haven\'t all been generals, or poets, or statesmen; but when the toast works down to the babies, we stand on common ground."'
var a = s.split(/;(?! )/,3)
console.log(a);

正则表达式 (/;(?!) 拆分所有“;”,除非后面有 space。

希望对您有所帮助!

好的,我创建了 PHP 拆分字符串算法的 4 个替代版本,以及 @hanshenrik 提供的两个版本,并对它们进行了基本基准测试:

function explode1(delimiter, str, limit) {
    if (limit == null) {
        return s.split(delimiter);
    }
    var a = [];
    var lastIndex = -1;
    var index = 0;
    for (var i = 0; i < limit; i++) {
        index = str.indexOf(delimiter, lastIndex + 1);
        if (i == limit - 1) {
            a.push(str.substring(lastIndex + 1));
        } else {
            a.push(str.substring(lastIndex + 1, index));
        }
        lastIndex = index;
    }
    return a;
}

function explode2(delimiter, str, limit) {
    if (limit == null) {
        return s.split(delimiter);
    }
    var a = str.split(delimiter);
    var ret = a.slice(0, limit - 1);
    ret.push(a.slice(limit - 1).join(delimiter));
    return ret;
}

function explode3(delimiter, str, limit) {
    if (limit == null) {
        return s.split(delimiter);
    }
    var a = s.split(delimiter, limit - 1);
    var index = 0;
    for (var i = 0; i < limit - 1; i++) {
        index = s.indexOf(delimiter, index + 1);
    }
    a.push(str.substring(index + 1));
    return a;
}

function explode4(delimiter, str, limit) {
    if (limit == null) {
        return s.split(delimiter);
    }
    var a = str.split(delimiter, limit - 1);
    a.push(str.substring(a.join(delimiter).length + 1));
    return a;
}

function explode5(delimiter, string, limit) {
    //  discuss at: http://locutus.io/php/explode/
    // original by: Kevin van Zonneveld (http://kvz.io)
    //   example 1: explode(' ', 'Kevin van Zonneveld')
    //   returns 1: [ 'Kevin', 'van', 'Zonneveld' ]

    if (arguments.length < 2 ||
        typeof delimiter === 'undefined' ||
        typeof string === 'undefined') {
        return null
    }
    if (delimiter === '' ||
        delimiter === false ||
        delimiter === null) {
        return false
    }
    if (typeof delimiter === 'function' ||
        typeof delimiter === 'object' ||
        typeof string === 'function' ||
        typeof string === 'object') {
        return {
            0: ''
        }
    }
    if (delimiter === true) {
        delimiter = '1'
    }

    // Here we go...
    delimiter += ''
    string += ''

    var s = string.split(delimiter)

    if (typeof limit === 'undefined') return s

    // Support for limit
    if (limit === 0) limit = 1

    // Positive limit
    if (limit > 0) {
        if (limit >= s.length) {
            return s
        }
        return s
            .slice(0, limit - 1)
            .concat([s.slice(limit - 1)
                .join(delimiter)
            ])
    }

    // Negative limit
    if (-limit >= s.length) {
        return []
    }

    s.splice(s.length + limit)
    return s
}

function explode6(delimiter, string, limit) {
        var spl = string.split(delimiter);
        if (spl.length <= limit) {
                return spl;
        }
        var ret = [],i=0;
        for (; i < limit; ++i) {
                ret.push(spl[i]);
        }
        for (; i < spl.length; ++i) {
                ret[limit - 1] += delimiter+spl[i];
        }
        return ret;
}

var s = 'Mark Twain,1879-11-14,"We haven\'t all had the good fortune to be ladies; we haven\'t all been generals, or poets, or statesmen; but when the toast works down to the babies, we stand on common ground."'
console.log(s);

console.time('explode1');
var a1 = explode1(',', s, 3);
//console.log(a1);
console.timeEnd('explode1');

console.time('explode2');
var a2 = explode2(',', s, 3);
//console.log(a2);
console.timeEnd('explode2');

console.time('explode3');
var a3 = explode3(',', s, 3);
//console.log(a3);
console.timeEnd('explode3');

console.time('explode4');
var a4 = explode4(',', s, 3);
//console.log(a4);
console.timeEnd('explode4');

console.time('explode5');
var a5 = explode5(',', s, 3);
//console.log(a5);
console.timeEnd('explode5');

console.time('explode6');
var a6 = explode6(',', s, 3);
//console.log(a6);
console.timeEnd('explode6');

两个性能最好的算法主要是 explode4explode3 在基准测试的多次迭代中紧随其后:

$ node explode1.js && node explode2.js && node explode3.js && node 
explode4.js && node explode5.js && node explode6.js
explode1: 0.200ms
explode2: 0.194ms
explode3: 0.147ms
explode4: 0.183ms
explode5: 0.341ms
explode6: 0.162ms

您可以 运行 您自己的基准测试,但通过我的测试,我可以确认将一个数组拆分为 n - 1,然后从加入生成的数组中获取索引是匹配 [=14= 的最快算法] 在 PHP.

编辑:事实证明,垃圾收集器对每个连续函数的测量方式存在偏差,因此我将它们拆分成各自的文件,并重新运行 几次基准测试。好像explode3是表现最好的,不是explode4,但我不会做出我不完全确定的决定。