Split string on every second space to isolate every two words
Asked Answered
B

10

3

Lets say I have a string:

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

If I do explode based on ' ' I get an

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

What I want is an explode for every other space:

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

The string may have an odd # of words, so the last item in the array may not contain two words.

Anyone know how to do this?

Borgeson answered 8/5, 2009 at 16:53 Comment(0)
E
11

I would look through the results, and concatenate the strings after the fact.

Ernestinaernestine answered 8/5, 2009 at 16:56 Comment(2)
Oh yeah good idea - a for loop that increments by two and concatenates - thanks.Borgeson
This answer looks like a comment by modern Stack Overflow standards. A more generous answer would actually show the coded implementation.Shaunshauna
A
8
$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);

yields:

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

)

update fixed it to match a single word at the end of the sentence

Astray answered 8/5, 2009 at 17:9 Comment(3)
Nice, add in if possible the check at the end to see if the last element has a single element as requested by the question.Solitary
Remove the surrounding parenthesis and you’ll get just one array.Anelace
Good work figuring it out, but I'm putting my +1 for Daniel's answer, sorry. Though this is correct and works, the other method would be more understandable and maintainable, IMO.Ophthalmitis
K
3

A function which can be used for different delimiters and numbers.

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

Test code

var_dump(explodeEveryNth(' ', 'This is a test string', 2));
Kung answered 11/5, 2009 at 21:50 Comment(1)
Yeah, that's definitely cleaner than mine. I like it! I was actually just exploring recursive function so I wanted to see if I could do it that way. I tested yours and it's way faster... For 1502 number of words: Chunk Explode = 0.49018907546997 seconds vs. Explode Every N = 0.0034539699554443 seconds.Punishment
F
2

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

preg_match_all("/[a-zA-Z0-9]+\ [a-zA-Z0-9]+/", $string, $matches);
print_r($matches);

Frum answered 8/5, 2009 at 17:10 Comment(2)
This will choke if non-alphanumeric characters are present in any of the words.Melina
So modify it: this is just an example.Frum
Q
1
$matches = array();
preg_match_all('/\S+(?:\s[A-Za-z0-9.]+|$)/',
    'This is my test case for an example.',
    $matches
);
print_r($matches);
preg_match_all('/\S+(?:\s[A-Za-z0-9.]+|$)/',
    'This is my test case for example.',
    $matches
);
print_r($matches);
Quahog answered 8/5, 2009 at 17:3 Comment(0)
P
1

Something You Can Re-Use for Other Scenarios: (always better IMO).

While probably not the most elegant solution, this does follow the general concept syntax of other PHP core functions...

In any case... This uses recursion. It is flexible in that it allows you to specify the size of the chunk (in case you'd like to do that down the road or for a different project). I did this as more of a personal challenge to see what I could come up with.

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

If this chunk_explode function sucks, let me know so I can learn from my mistakes.

Punishment answered 8/5, 2009 at 17:48 Comment(1)
Since you want notification, I got a different solution for this problem you might be interested in.Kung
T
1

There are 75 array functions in PHP, let's try to use them instead of for loops!!

I like Kyle's function name. (I'll assume you aren't running 5.3 and suffer with 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);
 }
Truncated answered 11/5, 2009 at 22:19 Comment(2)
array_map is slower then for loops. Its only usefull for iterating multiple arrays. create_function is also VERY slow, at least make a helper function or wait for PHP5.3.Kung
Array_map is more readable than for loops. My answer notes that PHP 5.3 avoid the create_function suffering, why did you reiterate what I said? Similarly, how do I pass $delim to a separate function called from array_map?Truncated
M
0
    $str = "This is my test case for an example.";
    $arr = split(' ', $str);
    $newArr = array();
    $count = count($arr);
    for($i=0;$i<$count;$i = $i + 2) {
        $newArr[] = $arr[$i] . ' ' . $arr[$i+1];
    }


array(4) {
  [0]=>
  string(7) "This is"
  [1]=>
  string(7) "my test"
  [2]=>
  string(8) "case for"
  [3]=>
  string(11) "an example."
}
Melina answered 8/5, 2009 at 17:12 Comment(0)
K
0

Well obviously this isn't the best solution, but it was fun figuring it out in my own way. Still so much to learn...

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!
Ka answered 9/5, 2009 at 16:37 Comment(0)
S
0

I wouldn't use any of the previously posted answers in my own project.

The cleanest, most direct tool is preg_split(). Match the first sequence of non-space characters, then a space, then the next sequence of non-space characters, then "forget" the matched characters and match the space which must be consumed during the exploding process.

\K means "restart the fullstring match from here". Using \K eliminates the need to implement a capture group as well as a PREG_ flag.

Code: (Demo)

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

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

Output:

array (
  0 => 'This is',
  1 => 'my test',
  2 => 'case for',
  3 => 'an example.',
)
Shaunshauna answered 5/9, 2020 at 11:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.