0

I'm creating a "quote database" for a TV show I'm a fan of, and I'm rewriting parts of it I don't particularly like. I came across my function to parse the data holding the quote and characters into an array that I can easily loop through and display. One of the features of the site is that you can have a single quote (one-liner) or a conversation between several characters. Right now I'm storing single quotes like this:

[charactername]This is my witty one-liner.

And conversations follow the same pattern:

[characternameone]How's the weather?

[characternametwo]Pretty good, actually.

And so on. Here's the aforementioned parsing function:

function parse_quote($text)
{
    // Determine if it's a single or convo
    if ( strpos($text, "\n") != false )
    {
        // Convo
        // Let's explode into the separate characters/lines
        $text = explode("\n", $text);
        $convo = array();

        // Parse each line into character and line
        foreach ( $text as $part )
        {
            $character = substr($part, 1, strpos($part, ']') - 1);
            $line = substr($part, strlen($character) + 2);
            $convo[] = array(
                'character' => $character,
                'line' => $line
            );
        }

        return array(
            'type' => 'convo',
            'quote' => $convo
        );
    }
    else
    {
        // Single
        // Parse line into character and line
        return array(
            'type' => 'single',
            'quote' => array(
                'character' => substr($text, 1, strpos($text, ']') - 1),
                'line' => substr($text, strlen(substr($text, 1, strpos($text, ']') - 1)) + 2)
            )
        );
    }
}

It works as expected, but I can't help but think there's a better way to do this. I'm horrible with regular expressions, which I assume would come in at least somewhat handy in this situation. Any advice, or improvements?

7
  • 1
    Yeah, use a database :) SQLite maybe Commented Mar 15, 2012 at 18:52
  • $text is coming from the database; that's how it's stored. How would I improve that? Perhaps I should serialize the thing before storing it? Commented Mar 15, 2012 at 18:54
  • 1
    Well, you didn't mentioned that, so I guessed "flat-file" meant just like that. An improvement? Use a column (in a table associated to the quote) for the character name so you don't have to parse anything but just use a select on properly indexed columns. Way easier and way more performant Commented Mar 15, 2012 at 18:55
  • Doesn't sound like a very interesting TV show. Commented Mar 15, 2012 at 18:56
  • You don't need regex. Sure, you could do it in fewer lines with a regular expression, but regex is much slower so simple tasks such as this should be done with string functions. Commented Mar 15, 2012 at 18:59

2 Answers 2

1

Personally, I would change your data storage method. It would be much easier to deal with a serialized or JSON encoded string.

Instead of

[characternameone]How's the weather?
[characternametwo]Pretty good, actually.

you would have

array(
  [0] => {
    'name'  => "characternameone",
    'quote' => "How's the weather?"
  },
  [1] => {
    'name'  => "characternametwo",
    'quote' => "Pretty good, actually"
  }
)

Then when you read it out, there isn't any parsing.

function display_quote($input)
{
  for ($i=0, $n=count($input); $i<$n; $i++) {
    $quote = $input[$i];
    if ( $i > 0 ) echo "\n";
    echo $quote['name'] . ': ' . $quote['quote'];
  }
}
Sign up to request clarification or add additional context in comments.

Comments

0

Instead of

        $character = substr($part, 1, strpos($part, ']') - 1);
        $line = substr($part, strlen($character) + 2);
        $convo[] = array(
            'character' => $character,
            'line' => $line
        );

you could try

        preg_match('#\[([^\]]+)\](.*)#ism', $part, $match);
        $convo[] = array(
            'character' => $match[1],
            'line' => $match[2]
        );

HTH

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.