Как сопоставить только буквы, встречающиеся в строке более одного раза, используя регулярные выражения? - PullRequest
1 голос
/ 09 июня 2019

Я пытаюсь сопоставлять только буквы, которые встречаются более одного раза (дважды или более) в строке, используя регулярное выражение для ruby. Я придумал регулярное выражение ниже, но, похоже, оно не работает. Я был бы признателен, если бы кто-то мог объяснить, почему мое регулярное выражение не работает, и рассказать мне, как оно должно быть, чтобы оно работало.

/[a-z]{2,}/

Ответы [ 4 ]

2 голосов
/ 09 июня 2019

Здесь мы можем просто использовать обратную ссылку с флагом i:

([a-z])\1

или без флага i:

([A-Za-z])\1

Демо

Тест

re = /([a-z])\1/im
str = 'a
ab
abc
1
22
22AB
AB
ABC
ABBC
ABBCCDD
'

# Print the match result
str.scan(re) do |match|
    puts match.to_s
end

RegEx

Если это выражение не нужно и вы хотите изменить его, перейдите по этой ссылке на regex101.com .

RegEx Circuit

jex.im визуализирует регулярные выражения:

enter image description here

Редактировать

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

([a-z])(?=[a-z]*\1)

Демо 2

Test

re = /([a-z])(?=[a-z]*\1)/
str = 'data
pattern
alice
bob
zdim
avery
paragraph
'

# Print the match result
str.scan(re) do |match|
    puts match.to_s
end

enter image description here

1 голос
/ 09 июня 2019

Здесь вам не нужно регулярное выражение.

"bananas".
    downcase.
    unicode_normalize(:nfc).
    each_char.
    with_object([Set.new, []]) do |e, (result, temp)|
  (temp.include?(e) ? result : temp) << e
end.first.to_a.join
#⇒ "an"

или:

"bananas".
    downcase.
    unicode_normalize(:nfc).
    chars.
    group_by(&:itself).
    reject { |_, e| e.count == 1 }.
    keys.
    join
#⇒ "an"
1 голос
/ 09 июня 2019

Было бы неплохо иметь возможность написать:

str.gsub(/(.)[^\1]*\z/i, '')

, но, увы, обратные ссылки (\1) не могут появляться в классах символов.

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

str = "bananas"

1.Преобразуйте буквы, которые следуют позже в строке той же буквой, в верхний регистр.
str1 = str.gsub(/(.)(?=.*\1)/) { |s| s.upcase }
  #=> "bANAnas

2.Удалите строчные буквы.
str2 = str1.gsub(/\p{Ll}/, '')
  #=> "ANA"

3.Удалите дубликаты оставшихся букв.
str3 = str2.gsub(/(.)(?=.*\1)/, '')
  #=> "NA"

4.Вниз str3 при желании.
str3.downcase
  #=> "na"

(?=.*\1) - это положительный прогноз .

Если требование использования регулярного выражения снято, можноwrite:

str.each_char.with_object(Hash.new(0)) { |c,h| h[c] += 1 }.
    select { |_,count| count > 1 }.
    keys
  #=> ["a", "n"]

Здесь

str.each_char.with_object(Hash.new(0)) { |c,h| h[c] += 1 }
  #=> {"b"=>1, "a"=>3, "n"=>2, "s"=>1}

Используется вторая форма Hash :: new , которая принимает аргумент, называемый значение по умолчанию .h[c] += 1 расширяется до h[c] = h[c] + 1.Если h не имеет ключа c, h[c] справа от равенства возвращает значение по умолчанию, равное нулю, что приводит к h]c] = 0 + 1.

0 голосов
/ 09 июня 2019

Если вам абсолютно необходимо использовать регулярные выражения, вы можете сначала отсортировать символы во входной строке, а затем использовать регулярное выражение для проверки повторяющихся символов (я бессовестно украл регулярное выражение из ответа @ AlekseiMatiushkin):

input = "A man a plan a canal Panama - Äpfelsäure".split()

re = /(\p{Ll})\1/

input.each do |w|
  sorted = w.downcase.unicode_normalize(:nfc).chars.sort().join()
  puts w if sorted =~ re
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...