Регулярное выражение для поиска чисел с одинаковыми цифрами в разном порядке - PullRequest
3 голосов
/ 22 октября 2009

Я искал регулярное выражение в Google в течение часа или около того и, похоже, не смог сработать: (

Если у меня есть номер, скажите:

2345

и я хочу найти любой другой номер с такими же цифрами, но в другом порядке, например:

2345

Например, я соответствую

3245 или 5432 (те же цифры, но в другом порядке)

Как бы я написал регулярное выражение для этого?

Ответы [ 7 ]

17 голосов
/ 22 октября 2009

Существует "элегантный" способ сделать это с помощью одного регулярного выражения:

^(?: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.

8 голосов
/ 22 октября 2009

Я не думаю, что регулярное выражение подходит. Итак, вот идея, которая быстрее, чем регулярное выражение для этой ситуации:

  • проверить длину строки, если они разные, вернуть false
  • сделать хэш от символа (цифры в вашем случае) до целых чисел для подсчета
  • перебирает символы вашей первой строки:
    • увеличить счетчик для этого символа: хэш [символ] ++
  • перебирает символы второй строки:
    • уменьшить счетчик для этого символа: хэш [символ] -
    • перерыв, если какое-либо количество является отрицательным (или не существует)
  • переберите записи, убедившись, что каждая из них равна 0:
    • если все равны 0, вернуть true
    • иначе вернуть false

РЕДАКТИРОВАТЬ: Java-код (я использую символ для этого примера, не совсем 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"));
    }
}

Это также будет работать для сравнения букв или других последовательностей символов, таких как «бог» и «собака».

3 голосов
/ 22 октября 2009

Поместите цифры каждого числа в два массива, отсортируйте массивы, выясните, содержат ли они одинаковые цифры с одинаковыми индексами.

RegExes не являются подходящим инструментом для этой задачи.

1 голос
/ 22 октября 2009

Вы можете сделать что-то вроде этого, чтобы обеспечить правильные символы и длину

 [2345]{4}

Убедиться, что они существуют только один раз, сложнее, и почему это не подходит для регулярных выражений

(?=.*2.*)(?=.*3.*)(?=.*4.*)(?=.*5.*)[2345]{4}
0 голосов
/ 22 октября 2009

Регулярные выражения не подходят для этой цели. Вот скрипт 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
0 голосов
/ 22 октября 2009

Я думаю, что очень просто добиться , если , вы в порядке с соответствием числа, которое не использует все цифры. Например. если у вас есть номер 1234 и вы принимаете совпадение с номером 1111 для возврата ИСТИНА;

Позвольте мне использовать 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.

0 голосов
/ 22 октября 2009

Самое простое регулярное выражение - это все 24 перестановки, добавленные с помощью оператора или:

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

Тем не менее, вы не хотите решать это с помощью регулярного выражения, если вам это сойдет с рук. Один проход через два числа в виде строк, вероятно, лучше: 1. Проверьте длину строки обеих строк - если они разные, все готово. 2. Создайте хэш всех цифр из числа, с которым вы сопоставляете. 3. Просмотрите цифры в проверяемом номере. Если вы нашли совпадение в хэше, отметьте его как использованный. Продолжайте до тех пор, пока не получите неиспользованный матч в хэше или не закончились элементы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...