2016-09-15 2 views
4

Я имею дело с радиосигналами, которые иногда имеют шумовые шипы.
вход что-то вроде этого:
00000001111100011110001111100001110000001000001111000000111001111000 Regex для устранения пиков шума сигнала бит

Перед синтаксического анализа данных в сигнале, нужно удалить шип биты, которые являются 0 и 1 в последовательность с длиной ниже (в данном примере) 3.

поэтому в основном я должен соответствовать 0000000111110001111000111110000111000000(1)000001111000000111(00)1111000
После матча я заменить его на немного, прежде чем он, так что чистый вид сигнала, как это: 00000001111100011110001111100001110000000000001111000000111111111000

до сих пор я достиг этого с двумя сиситемами аренда Regex:

self.re_one_spikes = re.compile("(?:[^1])(?P<spike>1{1,%d})(?=[^1])" % (self._SHORTEST_BIT_LEN - 1)) 
self.re_zero_spikes = re.compile("(?:[^0])(?P<spike>0{1,%d})(?=[^0])" % (self._SHORTEST_BIT_LEN - 1)) 

Затем я повторяю спички и заменяю.

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

re.compile("(?![\1])([01]{1,2})(?![\1])") 
+2

Таким образом, вы в основном хотят заменить любой изолированный одинарной или двойной 1 или 0 с 0 или 1 соответственно? –

+0

Да, не обязательно одиночные или двойные, но ниже определенного размера. – joaoricardo000

+0

Кроме того, что не так с двумя регулярными выражениями? Если вам не нравится дублирование кода (действительная точка), вы можете использовать одну строку шаблона и заменить на нее 0 и 1. –

ответ

6
import re 
THRESHOLD=3 

def fixer(match): 
    ones = match.group(0) 
    if len(ones) < THRESHOLD: return "0"*len(ones) 
    return ones 

my_string = '00000001111100011110001111100001110000001000001111000000111001111000' 
print(re.sub("(1+)",fixer,my_string)) 

, если вы также хотите удалить «пики» нулей

def fixer(match): 
    items = match.group(0) 
    if len(items) < THRESHOLD: return "10"[int(items[0])]*len(items) 
    return items 

print(re.sub("(1+)|(0+)",fixer,my_string)) 
+1

Nice and просто, но похоже, что OP также хочет удалить «пики» нулей. Но это можно было бы соответствующим образом адаптировать. –

+0

Отлично. Спасибо! – joaoricardo000

+0

@ joaoricardo000 Я думаю, вам следует обратиться к комментарию tobias_k по вашему вопросу ... в зависимости от того, как вы ответите, что это может усложниться: / –

0

Альтернативный подход без использования regex, и используя replace() вместо (в случае, если кто-то может оказаться полезным в будущем):

>>> my_signal = '00000001111100011110001111100001110000001000001111000000111001111000' 
>>> my_threshold = 3 
>>> for i in range(my_threshold): 
...  my_signal = my_signal.replace('0{}0'.format('1'*(i+1)), '0{}0'.format('0'*(i+1))) 
... 
>>> my_signal 
'00000001111100011110001111100000000000000000001111000000000001111000' 
0
def fix_noise(s, noise_thold=3): 
    pattern=re.compile(r'(?P<before>1|0)(?P<noise>(?<=0)1{1,%d}(?=0)|(?<=1)0{1,%d}(?=1))' % (noise_thold-1, noise_thold-1)) 
    result = s 
    for noise_match in pattern.finditer(s): 
     beginning = result[:noise_match.start()+1] 
     end = result[noise_match.end():] 
     replaced = noise_match.group('before')*len(noise_match.group('noise')) 
     result = beginning + replaced + end 
    return result 

Идентификационная идея Иордании int(items[0]) является удивительной!

1

Для согласования обоих случаях [01] в одном регулярном выражении, это просто:

(?<=([01]))(?:(?!\1)[01]){1,2}(?=\1)

Expanded

(?<=     # Lookbehind for 0 or 1 
     ([01])    # (1), Capture behind 0 or 1 
) 
(?:     # Match spike, one to %d times in length 
     (?! \1)    # Cannot be the 0 or 1 from lookbehind 
     [01] 
){1,2} 
(?= \1)    # Lookahead, can only be 0 or 1 from capture (1) 

Заменить $1 раз длина матча (то есть длина группы 0) ,

Матчи

** Grp 0 - (pos 40 , len 1) 
1 
** Grp 1 - (pos 39 , len 1) 
0 

---------------------------------------- 

** Grp 0 - (pos 59 , len 2) 
00 
** Grp 1 - (pos 58 , len 1) 
1 

Benchmark

Regex1: (?<=([01]))(?:(?!\1)[01]){1,2}(?=\1) 
Options: <none> 
Completed iterations: 50/50  (x 1000) 
Matches found per iteration: 2 
Elapsed Time: 2.06 s, 2058.02 ms, 2058018 µs 


50,000 iterations * 2 matches/iteration = 100,000 matches 

100,000 matches/2 sec's = 50,000 matches per second 
Смежные вопросы