-2

How can I split a multi line PHP var into a multi dimensional array that first breaks on newline \r\n|\r|\n char and then breaks each array down by word in a single fowl loop?

nanker
  • 593
  • 5
  • 12

1 Answers1

0

Like this

$text = <<<TEXT
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum 
TEXT;

$arr = array_map(function($item){return explode(' ',$item);},array_filter(array_map('trim',preg_split('/\r\n|\r|\n/',$text))));

print_r($arr);

Output

Array(
    [0] => Array(
            [0] => Lorem
            [1] => ipsum
            [2] => dolor
            ...
        )
    [1] => Array(
            [0] => Ut
            [1] => enim
            [2] => ad
            ...
        )
    [2] => Array(
            [0] => Duis
            [1] => aute
            ...
        )
)

Try it online

Explanation

  • <<<TEXT ... TEXT; is a HEREDOC its another way of doing strings, don't worry about it. I just like using it for big chunks of text, but it's not important to the answer.

Expanded Version

$arr = array_map(
    function($item){
        return explode(' ',$item);
    },array_filter(
        array_map(
            'trim',
            preg_split('/\r\n|\r|\n/',$text)
        )
    )
);

So lets work through it one at a time.

  1. First we do $arr = preg_split('/\r\n|\r|\n/',$text)
    • This splits the text into an array by using a Regex for line endings, we could have used [\r\n]+ which is a bit cleaner, but whatever. eg. ["Lorem ipsum", " ", " Duis aute irure"]
  2. Next we do $arr = array_map('trim', $arr)
    • array map calls a function (arg1) against each element in an array. So here we are trimming all the items with trim it removes leading and trailing space by default. Each item in the array item is a separate line of text (see above). eg. ["Lorem ipsum", "", "Duis aute irure"]
  3. Next we do $arr = array_filter($arr)
    • array filter removes any array elements that are empty. Because we trimmed some of these above it removes ones that had just whitespace too, eg. ["Lorem ipsum", "", "Duis aute irure"] the second item is removed eg. ["Lorem ipsum""Duis aute irure"]
  4. Next we run array map again
    • but this time with a custom inline function, which is applied to each item.
  5. This custom function in array_map
    • just does explode on spaces, which breaks all the words in to an array, which is also a nested array. We have to wrap explode in the closure, because it takes 2 arguments, where as trim takes only a single one. eg. [["Lorem","ipsum"],["Duis","aute","irure"]]

And that is it.

Additionally, you could further run:

function($item){
    return array_filter(array_map('trim', explode(' ', $item)));
}

If you have issues with spaces in the nested arrays. eg. [["Lorem","ipsum", " "],[" Duis","aute","irure"]].

Or you could also do it the following way. Which would be a bit better, because we are already in a loop like structure. So we would be calling this anonymous function 1 time per line in the text, and then adding another {n} calls in that.

function($item){
    return explode(' ', preg_replace('/\s{2,}/', ' ', $item));
    //trimming it, trim(preg_replace(...)) is not needed as it's already been trimmed.
}

This version will replace any double or more space \s{2,} before exploding it, which has roughly the same effect, but prevents the nested loopy-ness.

We can't do that easily in the beginning because we don't want to lose our \n line returns which are also matched by \s, for example sit amet \n which has a space and a new line. We would risk losing the \n if we are not careful, because \s{2,} matches it and would replace it with a single space.

-Note- preg_split and explode are similar, with the exception that the preg_split lets you use a regular expression. Which we need to account for different line endings from different OS's {ssSs}

(Win\r\n,Linux\n,Old Mac\r)

Function Reference

And (optionally)

Cheers!

ArtisticPhoenix
  • 21,464
  • 2
  • 24
  • 38
  • 1
    no, I thought it was self evident. I can explain if you want me to. – ArtisticPhoenix Apr 01 '18 at 04:04
  • I thought it was a site requirement to nut just dump code as an answer –  Apr 01 '18 at 04:15
  • 1
    I was being sarcastic, because I had already started explaining it. If anything I over explain. If you seen many of my answers that would be pretty clear. – ArtisticPhoenix Apr 01 '18 at 04:32
  • Good answer, poor question unfortunetly. – Scuzzy Apr 01 '18 at 04:32
  • 1
    @smith - I don't see where that was the case, but wtfe, if anything your tone was ... condescending at best. But whatever floats your boat as they say. – ArtisticPhoenix Apr 01 '18 at 05:00
  • 1
    @smith here are 3 answers I just recently did so if you think I was joking about over explaining, [one](https://stackoverflow.com/questions/49589410/instance-vs-static-method-calling-it-statically-or-dynamically/49589636#49589636) [two](https://stackoverflow.com/questions/49588111/php-recursion-issue-not-sending-back-values/49588571#49588571) [three](https://stackoverflow.com/questions/49585558/unable-to-show-comma-separated-values-in-a-table/49585586#49585586) you would find that you are mistaken. I can post many more if that doesn't convince you. – ArtisticPhoenix Apr 01 '18 at 05:04
  • Perfect solution and the detailed explanation was very helpful. Worked like a charm. – nanker Apr 01 '18 at 19:27