Как сопоставить разнесение PHP (';', $ s, 3) с s.split (';', 3) в JavaScript? - PullRequest
0 голосов
/ 31 октября 2018

Если вы запустите explode в PHP с ограниченной длиной результирующего массива, он добавит остаток строки к последнему элементу. Вот как должен вести себя разрыв строки, так как нигде в разделении я не говорю, что хочу отбросить моих данных, просто разделить их. Вот как это работает в 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 хотел использовать только первые два элемента в этом массиве, независимо от того, разделен массив или нет. Первые два элемента всегда будут иметь одинаковое значение, несмотря ни на что. Единственный элемент, который изменяется, это последний элемент массива разбиения.

Если нативный split с методом limit в JavaScript можно реплицировать с помощью slice, то какое значение он предоставляет?

Но я отступаю, какой самый эффективный способ воспроизвести функциональность explode в PHP? Удаление каждого элемента в качестве подстроки до достижения последнего элемента, разбиение всей строки, а затем конкатенация оставшихся элементов, получение местоположения разделителя n - 1 и получение его подстроки или любого другого решения, о котором я не думал

Ответы [ 3 ]

0 голосов
/ 31 октября 2018

Согласно документации, функция split принимает два аргумента:

string.split (разделитель, предел)

Однако это все равно не дает желаемого результата, потому что:

Второй параметр - это целое число, которое указывает число разбивает, элементы после предела разделения не будут включены в массив

Однако я заметил, что ';' в тексте есть пробел за ним. Таким образом, вы можете использовать регулярное выражение.

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);

Регулярное выражение (/; (?!) разбивает все ';', кроме случаев, когда за ним есть пробел.

Надеюсь, это поможет!

0 голосов
/ 05 ноября 2018

Хорошо, я создал 4 альтернативные версии алгоритма разделения строк PHP вместе с двумя, предоставленными @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');

Два самых эффективных алгоритма были explode4, в основном, с explode3 близкой секундой в нескольких итерациях теста:

$ 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 и последующее получение индекса от присоединения к результирующему массиву - самый быстрый алгоритм, соответствующий explode в PHP.

РЕДАКТИРОВАТЬ: Оказывается, сборщик мусора смещен, как была измерена каждая последующая функция, поэтому я разбил их на отдельные файлы и повторил тестирование несколько раз. Кажется, explode3 - лучший результат, а не explode4, но я не приму решение, в котором я не совсем уверен.

0 голосов
/ 31 октября 2018

Loctus.io помог вам, они перенесли взрыв php и множество других функций 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);

содержимое $ a, как сообщается консолью JavaScript Chrome:

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
}

edit: если по какой-то причине вам нужна / нужна меньшая реализация, вот 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;
}
...