正则表达式以不同的顺序查找具有相同数字的数字

时间:2009-10-22 13:13:15

标签: regex

我一直在寻找一个正常的表达方式与谷歌一个小时左右现在似乎无法解决这个问题:(

如果我有一个号码,请说:

2345

我希望找到具有相同数字但顺序不同的任何其他数字,如下所示:

2345

例如,我匹配

32455432(相同位数但订单不同)

我如何为此编写正则表达式?

7 个答案:

答案 0 :(得分:17)

使用单个正则表达式可以实现“优雅”的方式:

^(?:2()|3()|4()|5()){4}\1\2\3\4$

将以任何顺序匹配数字2,3,4和5。这四个都是必需的。

说明:

(?:2()|3()|4()|5())匹配数字2,3,4或5中的一个。现在的诀窍是,在匹配数字后,捕获括号匹配空字符串(总是成功)

{4}要求这种情况发生四次。

\1\2\3\4然后要求所有四个反向引用都参与了比赛 - 当且仅当每个数字发生一次时,他们才会这样做。由于\1\2\3\4匹配空字符串,因此只要前一个条件为真,它就会始终匹配。

对于五位数字,您需要

^(?:2()|3()|4()|5()|6()){5}\1\2\3\4\5$

等...

除了JavaScript之外,这几乎适用于任何正则表达式。

答案 1 :(得分:8)

我不认为正则表达式是合适的。所以这是一个比正则表达式更快的想法:

  • 检查字符串长度,如果它们不同,则返回false
  • 从字符(您的案例中的数字)到整数进行计数
  • 遍历第一个字符串的字符:
    • 增加该字符的计数器:hash [character] ++
  • 循环遍历第二个字符串的字符:
    • 减少该字符的计数器:hash [character] -
    • 如果任何计数为负(或不存在),则中断
  • 遍历条目,确保每个条目为0:
    • 如果全部为0,则返回true
    • else return false

编辑: Java代码(我在这个例子中使用了Character,不完全是Unicode友好的,但现在这个想法很重要):

import java.util.*;

public class Test
{
    public boolean isSimilar(String first, String second)
    {
        if(first.length() != second.length()) 
            return false;
        HashMap<Character, Integer> hash = new HashMap<Character, Integer>();
        for(char c : first.toCharArray())
        {
            if(hash.get(c) != null)
            {
                int count = hash.get(c);
                count++;
                hash.put(c, count);
            }
            else
            {
                hash.put(c, 1);
            }
        }
        for(char c : second.toCharArray())
        {
            if(hash.get(c) != null)
            {
                int count = hash.get(c);
                count--;
                if(count < 0)
                    return false;
                hash.put(c, count);
            }
            else
            {
                return false;
            }
        }
        for(Integer i : hash.values())
        {
            if(i.intValue()!=0)
                return false;
        }
        return true;
    }

    public static void main(String ... args)
    {
        //tested to print false
        System.out.println(new Test().isSimilar("23445", "5432"));

        //tested to print true
        System.out.println(new Test().isSimilar("2345", "5432"));
    }
}

这也适用于比较字母或其他字符序列,如“上帝”和“狗”。

答案 2 :(得分:3)

将每个数字的数字放在两个数组中,对数组进行排序,找出它们在相同索引处是否保持相同的数字。

RegExes不适合执行此任务。

答案 3 :(得分:1)

你可以这样做,以确保正确的字符和长度

 [2345]{4}

确保它们只存在一次比较棘手,为什么这不适合正则表达式

(?=.*2.*)(?=.*3.*)(?=.*4.*)(?=.*5.*)[2345]{4}

答案 4 :(得分:0)

最简单的正则表达式是通过or运算符添加的所有24个排列:

/ 2345 | 3245 | 5432 | ... /;

那就是说,你不想用正则表达式解决这个问题,如果你可以侥幸逃脱它。单个传递两个数字作为字符串可能更好:    1.检查两个字符串的字符串长度 - 如果它们不同则完成。    2.根据您匹配的数字构建所有数字的哈希值。    3.浏览您正在检查的号码中的数字。如果您在哈希中匹配匹配项,请将其标记为已使用。继续,直到你没有在哈希中使用未使用的匹配或用完项目。

答案 5 :(得分:0)

我认为实现如果你可以很好地匹配一个不使用所有数字的数字。例如。如果你有一个数字1234并且你接受一个数字为1111的匹配则返回TRUE;

让我使用PHP作为示例,因为您没有指定您使用的语言。

$my_num = 1245;
$my_pattern = '/[' . $my_num . ']{4}/'; // this resolves to pattern: /[1245]{4}/
$my_pattern2 = '/[' . $my_num . ']+/'; // as above but numbers can by of any length

$number1 = 4521;
$match = preg_match($my_pattern, $number1); // will return TRUE

$number2 = 2222444111;
$match2 = preg_match($my_pattern2, $number2); // will return TRUE

$number3 = 888;
$match3 = preg_match($my_pattern, $number3); // will return FALSE
$match4 = preg_match($my_pattern2, $number3); // will return FALSE

类似的东西也适用于Perl。

答案 6 :(得分:0)

正则表达式不适用于此目的。这是一个Perl脚本:

#/usr/bin/perl

use strict;
use warnings;

my $src = '2345';
my @test = qw( 3245 5432 5542 1234 12345 );

my $canonical = canonicalize( $src );

for my $candidate ( @test ) {
    next unless $canonical eq canonicalize( $candidate );
    print "$src and $candidate consist of the same digits\n";
}

sub canonicalize { join '', sort split //, $_[0] }

输出:

C:\Temp> ks
2345 and 3245 consist of the same digits
2345 and 5432 consist of the same digits