2013-05-08 79 views
7

我想利用一个和/或未知长度的逻辑查询查询字符串:PHP - 字符串逻辑解析 - “X AND Y OR Z”

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

它解析成一个数组,我假定将看起来是这样的:

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

这是我到目前为止有:

$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(); 
} 

任何更好的办法来解决呢?

+2

没有括号布尔*语言*没有多大意义。 – hek2mgl 2013-05-08 15:00:45

+2

在'或'上爆炸(')它会不会更容易,然后爆炸'和'上的每个片段?无可否认,这会给你一个空的数组,在你的样本字符串的末尾,你有“和和”,但你可以检查。 – andrewsi 2013-05-08 15:03:05

+0

是“和和”结尾的错字吗? – 2013-05-08 15:05:51

回答

4

更新:增加了使用& &和||的能力。随时随地

你可以做到以下几点:

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

这将导致以下:

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" 
    } 
} 
+0

这并没有'处理需要分割'&&'和'||'。 – cmbuckley 2013-05-08 15:09:29

+0

@cbuckley - 什么需要拆分&&和||?这个问题没有提到。 – andrewsi 2013-05-08 15:13:46

+0

在问题文本中没有明确提到,但是代码暗示了它的需要。 – cmbuckley 2013-05-08 15:14:34

2

如何:

$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); 
+0

有趣的是,最后一项是参考。 – user2362840 2013-05-08 15:26:59

+0

这与Mark Ba​​ker的回答共享问题,清理0个条目(它们本质上是相同的答案),但它也有点“太简单”。例如,如果我想处理手动分组“x和(y或z)和一个”。在优雅和效率类别中获得肯定的胜利。 – user2362840 2013-05-08 15:42:40

+0

@ user2362840 - 如果你想处理大括号,那么你使用了一个合适的词法分析器而不是简单的正则表达式......但是你并没有在你的原始问题中指出这一点。如果这是一项要求,那么答案会复杂得多 – 2013-05-08 15:46:32

1

使用explode是更简单:

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

,将返回:

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 
     ) 

) 
+0

除了大猩猩:) – 2013-05-08 15:10:57

+0

g OR illas。 LOL – 2013-05-08 15:12:26

+0

我忘了更改'或'为'或'后在爆炸:)后更新结果 – Alvaro 2013-05-08 15:12:30

3

这将处理gorillas问题,而空条目,如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); 

虽然array_filter也将清洁0进入

+0

在array_filter警告好点。 – cmbuckley 2013-05-08 15:16:16

1

什么我想我会去:

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