假设我有一个长字符串:
AX 90 10 20 AX 30 14 50 ER 40 50 68 ...
我需要的是
['AX 90 10 20', 'AX 30 14 50', 'ER 40 50 68',...]
我不想使用正则表达式,因为我会得到不同的重复模式,例如下面的示例,其中上面的正则表达式不适用于下面的
WE 12 (09/09) ER 14 (12/56) TO 90 (45/67) ...
对于第一个示例,我首先创建结构表示形式(将[A-Z]转换为“ A”,将[0-9]转换为“ 9”)
AX 90 10 20 AX 30 14 50 ER 40 50 68 ...
to
AA 99 99 99 AA 99 99 99 AA 99 99 99 ...
我的问题是,如何通过实时识别每个字符串中的模式然后获得匹配项?
注意: 模式未知,但已知某些字符会在一段时间后重复出现
我不想使用手动编写的正则表达式。如果系统生成正则表达式,那就没问题了。
答案 0 :(得分:3)
您可以尝试使用time series analysis
的季节性来依次获得相似的模式
为此,您可以尝试将字符串转换为整数,然后 使用statsmodels应用seasonal_decompose,然后您就可以从图形中观察重复模式的周期。
from matplotlib import pyplot
from statsmodels.tsa.seasonal import seasonal_decompose
a = 'AX 90 10 20 AX 30 14 50 ER 40 50 68'
a = list(map(ord,a))
series = pd.Series(a ,index = pd.date_range('1-1-2011',pd.to_datetime('1-1-2011')+np.timedelta64(len(a)-1,'D'),freq='D'))
result = seasonal_decompose(series, model='additive')
result.observed.plot()
result.trend.plot()
pyplot.rcParams["figure.figsize"] = (20,3)
pyplot.show()
然后在观察到的时间段内分割序列
修改
要在无需视觉检查的情况下找到序列的周期性,
我们可以使用autocorrelation以及信号的相关滞后来发现信号的周期性,从而显示出周期性。这样我们就可以对模式进行切片以检索相似的模式
def autocorr(x):
n = x.size
norm = (x - np.mean(x))
result = np.correlate(norm, norm, mode='same')
acorr = result[n//2 + 1:] / (x.var() * np.arange(n-1, n//2, -1))
lag = np.abs(acorr).argmax() + 1
return lag
period = autocorr(np.array(a))
#Here the pattern is repeating for each period of 12 values, you can pick the period also
period = 12
for i in range(0,len(a),period):
print(''.join(map(chr,a[i:i+period])))
出局:
AX 90 10 20
AX 30 14 50
ER 40 50 68
答案 1 :(得分:1)
如果您知道目标字符串都以N长度(此处为2个)大写字母开头,那么我不确定这是否那么复杂。
以下是可能的解决方案:
import re # only used in is_token, but not technically needed
def is_token(t):
return re.match(r'^[A-Z]+$', t)
def get_token_candidate_at(s, idx):
return s[idx:idx+2]
def emit_items(s):
delim_start = -1
for i,_ in enumerate(s):
token = get_token_candidate_at(s, i)
if is_token(token):
if delim_start >= 0:
yield s[delim_start:i]
delim_start = i
if delim_start > 0: # get the last one
yield s[delim_start:]
> list(emit_items("WE 12 (09/09) ER 14 (12/56) TO 90 (45/67)"))
['WE 12 (09/09) ', 'ER 14 (12/56) ', 'TO 90 (45/67)']
> list(emit_items("WE12(09/09)ER14(12/56)TO90(45/67)"))
['WE12(09/09)', 'ER14(12/56)', 'TO90(45/67)']
> list(emit_items("AZ893249EE886342TT125435"))
['AZ893249', 'EE886342', 'TT125435']
如果他们有不同的开始,则可以更改is_token
和get_token_candidate_at
以满足这些不同的要求。
如果模式确实是周期性的,那么您也许可以摆脱类似于频率分析的问题,但随后您必须了解有关“什么”是周期性的(例如“非数字是周期”),然后希望字符串足够长以提供有意义的周期性信号。这就是@zwer所得到的...“您期望的模式的属性是什么”。