我很清楚以下问题,该问题在堆栈溢出String Unknown pattern Matching上也存在,但是那里的答案对我来说真的不起作用。
下一个是我的问题。我得到一串字符,例如
- “ 1211”,我需要做的是看到最常重复1 并连续2次。
- 但是它也可以是“ 121212112”,其中12重复3次 行。
- 但是对于12221221,它是221,重复了2次而不是2次 重复3次。
这是我想要得到的一些结果(曾经使用过的唯一数字是1和2)
>>> counter('1211')
1
>>> counter('1212')
2
>>> counter('21212')
2
我想要的结果是它发生了多少次。
我不知道该如何开始寻找一种模式,因为它不是正手就知道的,而且我在网上做了一些研究,没有发现任何类似的东西。
有人知道我怎么开始解决这个问题吗?欢迎所有帮助,如果您需要更多信息,请随时告诉我。
答案 0 :(得分:2)
效率很低,但是您可以
很明显,您可以使用一些数据结构一次通过字符串并进行一些计数,但是由于我不确定您的约束和期望的输出是什么,因此我只能给您这个信息。
答案 1 :(得分:0)
我同意Jirka的看法,不确定要如何选择最佳成绩的长还是短得分,但是此功能将为您提供菜单:
#Func1
def sub_string_cts(string):
combos = {}
for i in range(len(string)):
u_start = len(string) - i
for start in range(u_start):
c_str = string[start:i+start+1]
if c_str in combos:
combos[c_str] += 1
else:
combos[c_str] = 1
return combos
sub_string_cts('21212')
{'2': 3,
'1': 2,
'21': 2,
'12': 2,
'212': 2,
'121': 1,
'2121': 1,
'1212': 1,
'21212': 1}
发表评论后,我认为这是您所寻找的更多内容:
#Func2
def sub_string_cts(string):
combos = {}
for i in range(len(string)):
u_start = len(string) - i
substrs = set([string[start:i+start+1] for start in range(u_start)])
for substring in substrs:
combos[substring] = max([len(i) for i in re.findall("((?:{})+)".format(substring), string)])//len(substring)
return combos
sub_string_cts('21212')
{'2': 1,
'1': 1,
'21': 2,
'12': 2,
'212': 1,
'121': 1,
'2121': 1,
'1212': 1,
'21212': 1}
您可以通过折叠每个字符串长度最高的出现实例,将其范围缩小到“最佳”候选:
def max_by_len(result_dict):
results = {}
for k, v in result_dict.items():
if len(k) not in results:
results[len(k)] = {}
for c_len in [ln for ln in results]:
len_max_count = max([v for (k, v) in result_dict.items() if len(k) == c_len])
for k,v in result_dict.items():
if len(k) == c_len:
if v == len_max_count:
results[c_len][k] = v
return results
#Func1:
max_by_len(sub_string_cts('21212'))
{1: {'2': 3},
2: {'21': 2, '12': 2},
3: {'212': 2},
4: {'2121': 1, '1212': 1},
5: {'21212': 1}}
#Func2:
max_by_len(sub_string_cts('21212'))
{1: {'2': 1, '1': 1},
2: {'21': 2, '12': 2},
3: {'212': 1, '121': 1},
4: {'2121': 1, '1212': 1},
5: {'21212': 1}}
假设我们不会选择“ 2121”或“ 1212”,因为它们的出现与“ 21212”相匹配且长度较短,并且类似地,我们也不会选择“ 21”或“ 12”,因为它们出现在与“ 212”的频率相同,我们可以使用以下代码将可行的候选对象限制为“ 2”,“ 212”和“ 21212”:
def remove_lesser_patterns(result_dict):
len_lst = sorted([k for k in result_dict], reverse=True)
#len_lst = sorted([k for k in max_len_results])
len_crosswalk = {i_len: max([v for (k,v) in result_dict[i_len].items()]) for i_len in len_lst}
for i_len in len_lst[:-1]:
eval_lst = [i for i in len_lst if i < i_len]
for i in eval_lst:
if len_crosswalk[i] <= len_crosswalk[i_len]:
if i in result_dict:
del result_dict[i]
return result_dict
#Func1
remove_lesser_patterns(max_by_len(sub_string_cts('21212')))
{1: {'2': 3}, 3: {'212': 2}, 5: {'21212': 1}}
#Func2
remove_lesser_patterns(max_by_len(sub_string_cts('21212')))
{2: {'21': 2, '12': 2}, 5: {'21212': 1}}
结果:
test_string = ["1211", "1212", "21212", "12221221"]
for string in test_string:
print("<Input: '{}'".format(string))
c_answer = remove_lesser_patterns(max_by_len(sub_string_cts(string)))
print("<Output: {}\n".format(c_answer))
<Input: '1211'
<Output: {1: {'1': 2}, 4: {'1211': 1}}
# '1' is repeated twice
<Input: '1212'
<Output: {2: {'12': 2}, 4: {'1212': 1}}
# '12' is repeated twice
<Input: '21212'
<Output: {2: {'21': 2, '12': 2}, 5: {'21212': 1}}
# '21' and '12' are both repeated twice
<Input: '12221221'
<Output: {1: {'2': 3}, 3: {'221': 2}, 8: {'12221221': 1}}
# '2' is repeated 3 times, '221' is repeated twice
这些函数一起为您提供每种图案出现次数最多的长度。字典的关键是长度,其子字典具有最高的出现模式(如果并列,则为多个)。
Func2要求模式是顺序的,而Func1则不需要-严格基于出现。
以您的示例为例:
3. But with 12221221 it is 221 that is repeated 2 times rather than 2 that repeats 3 times.
代码为您提供了以下两种解决方案,以解决您期望的输出(2或3)中的歧义:
<Input: '12221221'
<Output: {1: {'2': 3}, 3: {'221': 2}, 8: {'12221221': 1}}
# '2' is repeated 3 times, '221' is repeated twice
如果您只对2个字符长度感兴趣,则可以按照以下步骤轻松地将其从max_by_len
结果中拉出:
test_string = ["1211", "1212", "21212", "12221221"]
for string in test_string:
print("<Input: '{}'".format(string))
c_answer = remove_lesser_patterns({k:v for (k,v) in max_by_len(sub_string_cts(string)).items() if k == 2})
print("<Output: {}\n".format(max([v for (k,v) in c_answer[2].items()])))
#Func2
<Input: '1211'
<Output: 1
<Input: '1212'
<Output: 2
<Input: '21212'
<Output: 2
<Input: '12221221'
<Output: 1