匹配数字与预定义模式

时间:2015-08-22 20:51:58

标签: php mysql regex search

我有一个问题,我一直在思考,但未能找到最佳解决方案。

该应用程序适用于根据数字模式销售不同价格的特殊电话号码的公司。

所以用户有一个数字库存。并使用一些约定定义模式。例如:

  • (ABCDEFG)表示具有序列的数字,例如(1234567,或 2345678等...)。
  • (ZYX-ZYXW)代表一个数字,如(654-6543)。

当客户拿起一个号码时,该号码应与其匹配的模式匹配,当匹配一个模式时,该号码将按匹配模式的价格收费。

我的想法集中在三种可能的解决方案上:

  1. 我试着想一下正则表达式。但不确定它是否可以 工作。
  2. 另一种解决方案是循环每种可能性 对于每个模式并将其与购买的数字相匹配。但是我 我相信这将是太昂贵的表现明智。
  3. 最后我想在用户添加时保存所有可能的数字 模式,以便当客户想要购买新号码时, 应用程序不搜索模式但搜索实际数字。这个 当用户添加模式时,性能瓶颈的方式 (这比选择号码的客户要少得多)。
  4. 对于我应该使用哪种方法,你们有什么建议吗?非常感谢任何提示。

    修改

    我很高兴收到的回复。他们都很有启发性,但到目前为止还没有解决我的问题。真实场景将具有以下条件:

    • 某些模式将遵循某种数字顺序(顺序或非顺序),例如:ABCDEFG = 1234567或ACEGECA = 2468642。
    • 一些模式将基于重复的数字,例如:xyxyxyx = 1919191,或xyxzxyx = 2829282。我想在某种程度上我们可以将这个条件包含在上面的那个条件中。
    • 某些模式将具有硬编码数字,如ABC0ABC或123xyxy
    • 模式可能性没有限制。

    到目前为止,所有提议的方法都有其自身方式的限制。我仍然想到它,所以如果你想出任何有用的打击,请与我分享!

2 个答案:

答案 0 :(得分:2)

一个想法。 demo

$number = '987-9876';
$suffix = <<<'EOD'
0123456789 ABCDEFG 10 ABCABCD 15
9876543210 GFEDCBA 8 DCBDCBA 13
EOD;

$pattern = <<<'EOD'
~
\A (?<number>(\d{3})-?(\d{4})) \R 
(?|
    \d*? # rectus
    (?|
        \2 \3 \d*
        [ ] (?<format> ABCDEFG ) [ ] (?<price>\d+)
      |
        (?=\3) \2 \d*
        (?> [ ] [A-Z]+ [ ] \d+)*? # other formats until the good one
        [ ] ( ABCABCD ) [ ] (\d+)
    )
  |
    .* \R \d*? # inversus
    (?|
        \2 \3 \d*
        [ ] ( GFEDCBA ) [ ] (\d+)
      |
        (?=\3) \2 \d*
        (?> [ ] [A-Z]+ [ ] \d+)*?
        [ ] ( DCBDCBA ) [ ] (\d+)
    )
)
~x
EOD;

if (preg_match($pattern, $number . PHP_EOL . $suffix, $m))
    echo 'number: ' . $m['number'] . PHP_EOL . 'format: ' . $m['format'] . PHP_EOL
       . 'price: ' . $m['price'];

其他方法 (可能效果最佳)

特殊号码有限。您可以生成并使用包含所有特殊数字的多维数组,如下所示:

$speNum = [
    'ABCDEFG' => [ '1234567', '2345678', '3456789' ],
    'GFEDCBA' => [ '9876543', '8765432', '7654321' ],
    'ABCABCD' => [ '1231234', '2342345' ... 
];

$prices = [ 'ABCDEFG' => 10, 'ABCABCD' => 15, 'GFEDCBA' => 8 ...];

使用简单的foreach,测试数字是否在数组中:

foreach ($speNum as $format => $nums) {
    if (in_array($number, $nums)) {
        echo 'number: ' . $number . PHP_EOL . 'format: ' . $format . PHP_EOL
           . 'price: ' . $prices[$format];
        break;
    }
}

注意:对于第二种方法(为什么不是第一种方法),请先删除连字符。这种方法的主要优点是您可以轻松地将其扩展到其他类型的模式。请注意,您可以对数据库执行相同的操作。

答案 1 :(得分:1)

使用以下策略: 伪代码

String getPattern(String pn,int n) 
    {

        int[] nums = new int[7];
        for (int i = 0; i < 7; i++)
            nums[i] = int.Parse(pn[i].ToString());
        Array.Sort(nums);
        String pat = pn;
        Char chr = 'A';
        for (int i = 0; i < 7; i++)
        {
            if (nums[i] != n)
            {
                pat = pat.Replace(nums[i].ToString(), chr.ToString());
                if ((i + 1) < 7)
                {
                    int shif = nums[i + 1] - nums[i];
                    chr = (Char)(Convert.ToUInt16(chr) + shif);
                }
            }

        }
        return pat;
    }

它使用c#为我工作,它会自动检测输入数字的模式 你也可以将它发展得更高级(例如添加zyx模式检测)

enter image description here