<\/script>')

PHP - Logical Analysis String - "X AND Y OR Z"

I would like to take a query string and / or a logical query of unknown length:

$logic = 'elephants and tigers or dolphins and apes or monkeys and humans and gorillas and and 133322 or 2'; 

And parse it into an array, I assume it will look something like this:

 $parsed_to_or = array( array('elephants', 'tigers'), array('dolphins', 'apes'), array('monkeys', 'humans', 'gorillas', '133322'), array('2') ); 

This is what I still have:

  $logic_e = preg_split('/\s+/', $logic); $or_segments = array(); $and_group = array(); foreach($logic_e as $fragment) { if (preg_match('/^(and|&&)$/i', $fragment)) { continue; } elseif (preg_match('/^(or|\\|\\|)$/i', $fragment)) { if (count($and_group)>0) { $or_segments[] = $and_group; $and_group = array(); } continue; } else { $and_group[] = $fragment; continue; } } if (count($and_group)>0) { $or_segments[] = $and_group; $and_group = array(); } 

Any better ways to solve this problem?

+7
source share
5 answers

Update: added the ability to use && and || anywhere

You can do the following:

 <?php $logic = 'elephants && tigers || dolphins && apes || monkeys and humans and gorillas and && 133322 or 2'; $result = array(); foreach (preg_split('/ (or|\|\|) /', $logic) as $parts) { $bits = preg_split('/ (and|&&) /', $parts); for ($x=0; $x<count($bits); $x++) { $bits[$x] = preg_replace('/\s?(and|&&)\s?/', '', $bits[$x]); } $result[] = $bits; } echo '<pre>'; var_dump($result); 

This will result in the following:

 array(4) { [0]=> array(2) { [0]=> string(9) "elephants" [1]=> string(6) "tigers" } [1]=> array(2) { [0]=> string(8) "dolphins" [1]=> string(4) "apes" } [2]=> array(4) { [0]=> string(7) "monkeys" [1]=> string(6) "humans" [2]=> string(8) "gorillas" [3]=> string(6) "133322" } [3]=> array(1) { [0]=> string(1) "2" } } 
+4
source

This will handle the gorillas problem, and empty entries like and and

 $logic = 'elephants and tigers or dolphins and apes || monkeys and humans and gorillas and and 133322 or 2'; $arrayBlocks = preg_split('/(\bor\b|\|\|)/', $logic); array_walk( $arrayBlocks, function(&$entry, $key) { $entry = preg_split('/(\band\b|&&)/', $entry); $entry = array_filter( array_map( 'trim', $entry ) ); } ); var_dump($arrayBlocks); 

although array_filter will also clear record 0

+3
source

How about this:

 $logic = 'elephants and tigers or dolphins and apes or monkeys and humans and gorillas and and 133322 or 2'; $ors = preg_split('/(\bor\b|\s\|\|\s)/', $logic); foreach ($ors as &$or) { $or = array_filter(array_map('trim', preg_split('/(\band\b|\s&&\s)/', $or))); } var_dump($ors); 
+2
source

Using explode much simpler:

  $logic = 'elephants and tigers or dolphins and apes or monkeys and humans and gorillas and and 133322 or 2'; $parts = explode(" or ", $logic); foreach($parts as $part){ if(!empty($part)){ $finalArray[] = explode(" and ", $part); } } print_r($finalArray); 

This will return:

 Array ( [0] => Array ( [0] => elephants [1] => tigers ) [1] => Array ( [0] => dolphins [1] => apes ) [2] => Array ( [0] => monkeys [1] => humans [2] => gorillas [3] => and 133322 ) [3] => Array ( [0] => 2 ) ) 
+1
source

What I think I will go with:

 $or_segments = array(); foreach(preg_split('/((\\s+or\\s+|\\s*\\|\\|\\s*))+/i', $logic) as $or_split_f) { $or_segments[] = preg_split('/((\\s+and\\s+|\\s*&&\\s*))+/i', $or_split_f); } var_dump($or_segments); 
+1
source

All Articles