Взорваться над каждым другим словом

Допустим, у меня есть строка:

$string = "This is my test case for an example."

Если я взорвусь на основе ' ', я получу

Array('This','is','my','test','case','for','an','example.');

То, что я хочу, это взрыв для каждого другого пространства:

Array('This is','my test','case for','an example.').

В строке может быть нечетное количество слов, поэтому последний элемент массива не может содержать двух слов.

Кто-нибудь знает, как это сделать?


person Community    schedule 08.05.2009    source источник


Ответы (8)


Я бы просмотрел результаты и объединил строки постфактум.

person Daniel A. White    schedule 08.05.2009
comment
О да, хорошая идея - цикл for, который увеличивается на два и объединяется - спасибо. - person ; 08.05.2009
comment
Кажется, это самый простой способ сделать это. - person Andrew Szeto; 09.05.2009

$matches = array();
preg_match_all('/([A-Za-z0-9\.]+(?: [A-Za-z0-9\.]+)?)/',
       'This is my test case for an example.',$matches);

print_r($matches);

дает:

Array
(
  [0] => Array
    (
        [0] => This is
        [1] => my test
        [2] => case for
        [3] => an example.
    )

  [1] => Array
    (
        [0] => This is
        [1] => my test
        [2] => case for
        [3] => an example.
    )

)

обновление исправил его, чтобы он соответствовал одному слову в конце предложения

person Evert    schedule 08.05.2009
comment
Хорошо, добавьте, если возможно, проверку в конце, чтобы увидеть, есть ли в последнем элементе один элемент, как того требует вопрос. - person cgp; 08.05.2009
comment
Удалите окружающие скобки, и вы получите только один массив. - person Gumbo; 09.05.2009
comment
Хорошая работа, чтобы понять это, но я ставлю +1 за ответ Даниэля, извините. Хотя это правильно и работает, другой метод был бы более понятным и ремонтопригодным, ИМО. - person nickf; 09.05.2009

Функция, которую можно использовать для разных разделителей и чисел.

function explodeEveryNth($delimiter, $string, $n) {
    $arr = explode($delimiter, $string);
    $arr2 = array_chunk($arr, $n);
    $out = array();
    for ($i = 0, $t = count($arr2); $i < $t; $i++) {
        $out[] = implode($delimiter, $arr2[$i]);
    }
    return $out;
}

Тестовый код

var_dump(explodeEveryNth(' ', 'This is a test string', 2));
person OIS    schedule 11.05.2009
comment
Да, это определенно чище, чем у меня. Мне это нравится! На самом деле я просто изучал рекурсивную функцию, поэтому хотел посмотреть, смогу ли я сделать это таким образом. Я проверил ваш, и он намного быстрее ... Для 1502 количества слов: Chunk Explode = 0,49018907546997 секунд против Explode Every N = 0,0034539699554443 секунд. - person KyleFarris; 12.05.2009
comment
Спасибо! Работает на меня. - person skiindude22; 10.07.2017

Что-то, что вы можете повторно использовать для других сценариев (всегда лучше, IMO).

Хотя, вероятно, это не самое элегантное решение, оно следует общему концептуальному синтаксису других основных функций PHP...

В любом случае... Здесь используется рекурсия. Он гибкий в том смысле, что позволяет указать размер фрагмента (на случай, если вы захотите сделать это в будущем или для другого проекта). Я сделал это скорее как личный вызов, чтобы увидеть, что я могу придумать.

<?php
function chunk_explode($glue=' ',$pieces='',$size=2,$final=array()) {
    if(!is_string($pieces) && !is_array($pieces)) 
        return false;

    if(is_string($pieces))
        $pieces = explode($glue,$pieces);

    $num_pieces = sizeof($pieces);
    if($num_pieces <= 0) 
       return $final;

    if($num_pieces >= $size) {
        $arr_chunk = array_chunk($pieces, $size);
        array_push($final,implode($glue,$chunk[0]));
        for($i=0;$i<=$size;$i++) { array_shift($pieces); }
        return chunk_explode($glue,$pieces,$size,$final);
    }
    array_push($final,implode($glue,$pieces));
    return $final;
}
$string = "This is my test case for an example.";
chunk_explode(' ',$string,3);

Если эта chunk_explode функция отстой, дайте мне знать, чтобы я мог учиться на своих ошибках.

person KyleFarris    schedule 08.05.2009
comment
Поскольку вам нужно уведомление, у меня есть другое решение этой проблемы, которое может вас заинтересовать. - person OIS; 12.05.2009

В PHP есть 75 функций обработки массивов, давайте попробуем использовать их вместо циклов for!!

Мне нравится название функции Кайла. (Я предполагаю, что вы не используете 5.3 и страдаете от create_function.)

 function chunk_explode($string, $chunks = 2, $delim = ' ') {
     $A = explode($delim, $string);
     $A = array_chunk($A, $chunks);
     return array_map(
         create_function('$x',
            'return implode(\'' . $delim . '\',$x);'), $A);
 }
person jmucchiello    schedule 11.05.2009
comment
array_map медленнее, чем для циклов. Это полезно только для итерации нескольких массивов. create_function также ОЧЕНЬ медленный, по крайней мере, сделайте вспомогательную функцию или дождитесь PHP5.3. - person OIS; 13.05.2009
comment
Array_map более удобочитаем, чем циклы for. В моем ответе отмечается, что PHP 5.3 избегает страданий create_function, почему вы повторили то, что я сказал? Точно так же, как передать $delim отдельной функции, вызываемой из array_map? - person jmucchiello; 13.05.2009

Ну, очевидно, это не лучшее решение, но было забавно понять это по-своему. Еще столькому предстоит научиться...

function solveThisPuzzle($string) {

$modified_string = preg_replace('(\s)', '+', $string, -1, $count);  
$words = explode('+', $modified_string);

$phrases_arr = array();

for($i = 1; $i < $count+1; $i++) {
    if(($i % 2)) {
        $phrase = $words[$i-1].' '.$words[$i];
        $phrases_arr[] = $phrase;
        unset($phrases_arr[$i]);
    } elseif($i == $count) {
            $phrase = $words[$i];
            $phrases_arr[] = $phrase;
        } else {            
            $phrase = NULL;
        }
}

foreach($phrases_arr as $final_phrase) {
    $solution .= $final_phrase.'<br />';
}

    return $solution;

}

$string = "This is my test case for an example, huzzah!";
echo solveThisPuzzle($string);

This is
my test
case for
an example,
huzzah!
person Community    schedule 09.05.2009

Я бы не стал использовать ни один из ранее опубликованных ответов в своем собственном проекте.

Самый чистый и прямой инструмент — preg_split(). Сопоставьте первую последовательность символов без пробелов, затем пробел, затем следующую последовательность символов без пробелов, затем забудьте совпадающие символы и сопоставьте пробел, который должен быть использован во время процесса расширения.

\K означает перезапустить полное соответствие строки отсюда. Использование \K устраняет необходимость реализации группы захвата, а также флага PREG_.

Код: (Демо)

$string = "This is my test case for an example.";

var_export(
    preg_split('~[^ ]+ [^ ]+\K ~', $string)
);

Выход:

array (
  0 => 'This is',
  1 => 'my test',
  2 => 'case for',
  3 => 'an example.',
)
person mickmackusa    schedule 05.09.2020

person    schedule
comment
Это задохнется, если в любом из слов присутствуют не буквенно-цифровые символы. - person karim79; 08.05.2009
comment
Так что измените его: это всего лишь пример. - person Andrew Sledge; 08.05.2009