我正在尝试解析从hashtag获取的字符串,到目前为止看起来像正则表达式可能是最干净的方法。该模式有一个解释,如下:
#p3 -> p = 3
#h4 -> h = [ 4 ]
#h4,h6 -> h = [ 4, 6 ]
#p3,h4,h6 -> p = 3, h = [ 4, 6 ]
#h4,h6,p3 -> p = 3, h = [ 4, 6 ]
#h4s2,6,10 -> h = [ 4 ], s = { "4": [ 2, 6, 10 ] }
#h4s2,6,10,h6s5 -> h = [ 4, 6 ], s = { "4": [ 2, 6, 10 ] , "6": [ 5 ] }
#p20h4s2,6,10,h6s5,1 -> p = 20, h = [ 4, 6 ], s = { "4": [ 2, 6, 10 ] , "6": [ 5, 1 ] }
正如我所说,我认为正则表达式可能是我最好的选择,但它也是任何复杂的弱点。
如果您有其他建议/解决方案,那么我欢迎他们。我可以使用if/else
和大量indexOf
以及splits
来执行此操作,等等......但我确信必须有更好的方法。
更新:左边的输出最好被视为解释。虽然这是期望的最终结果,但正则表达式解决方案不必解决完整问题,但可能让我参与其中。另外,重申一下,我正在使用 Javascript 。
答案 0 :(得分:5)
您可以使用单个表达式来确定特定行是否有效,但如果您尝试基于输入字符串构建结构,那么您应该采用两步标记化/解析方案因为这会简化事情。
根据它的外观,您有三种类型的令牌:p
,h
和s
。每个标记都是一个字母,后跟一个数字(在s
的情况下后跟更多的数字)。
所以我开始使用一个tokenizer,用于将字符串转换为一系列抽象标记。可以使用正则表达式匹配每个标记。
我们取这个字符串:#p20h4s2,6,10,h6s5,1
。虽然仍有输入,但您将根据剩余输入创建一系列令牌。
您的第一个令牌是p
,其值为20
。然后,您有h
,其值为4
。然后是值s
的{{1}},依此类推。要确定哪个令牌是哪个,请使用非常简单的正则表达式。 [2,6,10]
的表达式可以是p
。 p\d+
可能是h
。 h\d+
看起来像s
。
标记化步骤的结果是一系列对象,如下所示:s(\d+)(,\d+)*
。此时,您可以确定{ p(20), h(4), s(2,6,10), h(6), s(5,1) }
是s(2,6,10)
的一部分,并构建您的结构,而不必担心结构的字符串表示。
现在,至于在JavaScript中实际实现它,它不会太难。令牌序列可以是一个数组,您可以使用if / else块和上面的正则表达式找到令牌。
重要的是分离你正在使用字符串表示的部分(标记化)和你正在使用抽象表示的部分(解析)。它使概念上的事情变得更加简单。如果您以后需要它们,也可以通过这种方式添加新类型的令牌。
答案 1 :(得分:2)
这是一些代码。
var p, h = [], s = {};
var re = /[ph][0-9]+|s[0-9,]*[0-9]/g;
var a;
while ((a = re.exec(myhashtag)) !== null) {
var first = a[0].substring(0, 1);
var rest = a[0].substring(1);
if (first == 'p')
p = parseInt(rest);
else if (first == 'h')
h.push(parseInt(rest));
else {
a = rest.split(',');
for (var i = 0; i < a.length; i++)
a[i] = parseInt(a[i]);
s[h[h.length - 1]] = a;
}
}
这仅使用正则表达式来查找看起来像p3
或h4
或s3,4,5
的所有主题标签。其余的只是常规的JavaScript。
此代码非常 lax。如果hashtag中包含无法解析的垃圾,例如#p3_banana_*q4
,则此代码只会忽略它。如果hashtag包含这样的废话,那么编写更严格的代码会抛出错误可能会更好。
答案 2 :(得分:0)
正则表达式用于确定给定模式是否存在,并且可能对其起作用(替换,移除等)。你想做更多的事情;你想确定一个模式是否存在,然后根据它进行某种解析。如果是我,我会按如下方式执行它(下面的伪代码):
if(string_begins_with('#')) { if(string_contains('p')) { // get numbers following using some "CSV-to-array" function } if(string_contains('h') { foreach('h') { // check for 's' following, do csv-to-array thing } } }
编辑:如果你真的想走这条路,你将不得不使用前瞻。假设p
在开头是固定的:
/
^\#
(p[\d,]+)? # find the 'p'
( # beginning of 'find the "h"' code
h([[0-9],]) # find the 'h'
(?= # beginning of lookahead for 's'
(s([[0-9],])+)? # code for s, including a final ? since it may not
# be there at all. I'm not sure if this part will work.
) # end of lookahead
)+ # end of code for 'h', + since you may have more than one 'h'
/
这可能需要一些工作,但这是一个开始。