2011-04-25 32 views
0

所以我正在使用Shunting-Yard算法处理来自XML字符串的一些数学运算。诀窍是我想通过使用逗号分隔列表来允许随机值的生成。例如...在调车场之前处理逗号分隔列表

((3 + 4) * 12) * (2, 3, 4, 5)) 

我已经有一个基本的Shunting-Yard处理器工作。但是我想在处理表达式之前预处理字符串以从列表中随机选择一个值。这样,我可能会结束:

((3 + 4) * 12) * 4) 

分流码的设置已经是相当复杂的,就我的理解而言,所以我很犹豫,试图改变它来处理这个问题。处理错误检查听起来像一场噩梦。因此,我认为事先寻找这种模式是有意义的?我正在考虑使用一个正则表达式,但我不是“那些”人之一......虽然我希望我是......而当我找到一些examples时,我不确定我会如何修改它们首先检查括号?我也不相信这将是最好的解决方案。请注意,如果解决方案是正则表达式,它应该能够在逗号列表中匹配字符串(只是字符,无符号),因为我将在我的分流中处理特定的字符串值 - 实施。

感谢您的提前想法。

+0

您正在使用什么语言,解析这个? – ridgerunner 2011-04-25 14:53:40

+0

AS3,所以虽然我很欣赏具体的答案,但我试着让问题更一般。 – grey 2011-04-26 03:17:55

+1

当提出正则表达式问题时,指定语言很重要,因为每种语言都有不同的正则表达式能力(正确答案取决于这些能力)。例如,现在我知道您正在使用AS3(使用Javascript正则表达式“flavor”),实际上正确的答案是简化的。看到我更新的答案。 – ridgerunner 2011-04-26 13:53:37

回答

1

这很容易解决使用两个正则表达式。适用于整体文本的第一个正则表达式匹配逗号分隔值的每个加括号列表。应用于每个先前匹配列表的第二个正则表达式匹配列表中的每个值。下面是有功能的PHP脚本,考虑具有多个列表的输入文本,替换其值中的一个随机选择的每个列表:

<?php // test.php 20110425_0900 

function substitute_random_value($text) { 
    $re = '/ 
     # Match parenthesized list of comma separated words. 
     \(   # Opening delimiter. 
     \s*   # Optional whitespace. 
     \w+   # required first value. 
     (?:   # Group for additional values. 
      \s* , \s* # Values separated by a comma, ws 
      \w+  # Next value. 
     )+   # One or more additional values. 
     \s*   # Optional whitespace. 
     \)   # Closing delimiter. 
     /x'; 
    // Match each parenthesized list and replace with one of the values. 
    $text = preg_replace_callback($re, '_srv_callback', $text); 
    return $text; 
} 
function _srv_callback($matches_paren) { 
    // Grab all word options in parenthesized list into $matches. 
    $count = preg_match_all('/\w+/', $matches_paren[0], $matches); 
    // Randomly pick one of the matches and return it. 
    return $matches[0][rand(0, $count - 1)]; 
} 

// Read input text 
$data_in = file_get_contents('testdata.txt'); 

// Process text multiple times to verify random replacements. 
$data_out = "Run 1:\n". substitute_random_value($data_in); 
$data_out .= "Run 2:\n". substitute_random_value($data_in); 
$data_out .= "Run 3:\n". substitute_random_value($data_in); 

// Write output text 
file_put_contents('testdata_out.txt', $data_out); 

?> 

substitute_random_value()函数调用PHP preg_replace_callback()功能,它匹配和用列表中的一个值替换每个列表。它调用_srv_callback()函数,随机选取其中一个值并将其作为重置值返回。

鉴于这种输入测试数据(testdata.txt):

((3 + 4) * 12) * (2, 3, 4, 5))
((3 + 4) * 12) * (12, 13))
((3 + 4) * 12) * (22, 23, 24))
((3 + 4) * 12) * (32, 33, 34, 35))

这里是从脚本的一个例子的运行的输出:

Run 1:

((3 + 4) * 12) * 13)
((3 + 4) * 12) * 22)
((3 + 4) * 12) * 35)
Run 2:
((3 + 4) * 12) * 3)
((3 + 4) * 12) * 12)
((3 + 4) * 12) * 22)
((3 + 4) * 12) * 33)
Run 3:
((3 + 4) * 12) * 3)
((3 + 4) * 12) * 12)
((3 + 4) * 12) * 23)
((3 + 4) * 12) * 32)

注意,该解决方案使用\w+以匹配由 “字” 的字符,即,[A-ZA-Z0-9_]值。如果这不符合您的要求,可以轻松更改。

编辑:这里是substitute_random_value()功能的JavaScript版本:

function substitute_random_value(text) { 
    // Replace each parenthesized list with one of the values. 
    return text.replace(/\(\s*\w+(?:\s*,\s*\w+)+\s*\)/g, 
     function (m0) { 
      // Capture all word values in parenthesized list into values. 
      var values = m0.match(/\w+/g); 
      // Randomly pick one of the matches and return it. 
      return values[Math.floor(Math.random() * values.length)]; 
     }); 
} 
+0

谢谢。我会试试这个报告。 – grey 2011-04-25 19:45:46

+0

感谢您的澄清。它很好地完成了这项工作。 – grey 2011-04-26 19:01:42

+0

\(\ s * \ - ?\ w +(?:\ s *,\ s * \ - ?\ w +)+ \ s * \)&\ - ?\ w + - 我做了一个修改,添加\ - ? \ w's之前也要匹配负数。在其他人需要的情况下。 – grey 2011-04-27 02:58:06