列表识别与解析的java算法

kxe2p93d  于 2021-06-30  发布在  Java
关注(0)|答案(9)|浏览(296)

我有数据,理论上是一个列表,但历史上一直是由用户作为一个自由形式的文本字段输入。现在我需要将列表中的每一项分开,以便对每个元素进行分析。
用户输入我的数据的简化示例:

one, two, three, four, five 

one. two. three, four. five.

"I start with one, then do two, maybe three and four then five"

one  
two  
three  
four  
five.  

one, two. three four five

one two three four - five

"not even a list, no list-elements here! but list item separators may appear. grrr"

所以,这或多或少就是数据的样子。实际上,一个列表项可能有几个单词长。我需要处理这些列表(其中有数千个),以便最终得到如下数组:

array[0] = "one"  
array[1] = "two"  
array[n] = n

我接受有时我的算法将完全无法解析列表,我不需要100%的成功率,75%就好了。误报对我来说是非常昂贵的,所以我宁愿完全拒绝一个列表,也不愿生成一个不包含真实数据的列表——假设一些用户输入了毫无意义的胡言乱语。
我有一些想法,可以尝试确定正在使用的分隔符,以及与内容大小相关的数据分隔规则。
我更喜欢java或python,不过欢迎任何解决方案:-)

agxfikkp

agxfikkp1#

我不确定最好的答案到底是什么,但如果你需要有一些误报,那么也许你应该做的是定义一些很可能是列表的模式,并严格拒绝所有其他数据。

patterns = [
    re.compile(r'^\s*(\w+)(\s*,\s*(\w+))*\s*$'), 
    re.compile(r'^\s*(\w+)(\s*\.\s*(\w+))*\s*$'), 
    re.compile(r'^\s*(\w+)(\s*,\s*(\w+))*\s+and\s+(\w+)\s*^$')
]
acceptSet = [ line for line in candidateSet if 
              any(pattern.match(line) for pattern in patterns)]
uidvcgyl

uidvcgyl2#

我不知道我是否理解你的问题。如果您想从python中混乱的字符串中提取字母数字字符串,应该是:

>>> import re
>>> re.split('\W+','abaa, asodf ?. poasid - paosfi sec')
['abaa', 'asodf', 'poasid', 'paosfi', 'sec']

或者如果你知道分隔符:

>>> re.split('[,. -]+','abaa, asodf, poasid - paosfi sec')
['abaa', 'asodf', 'poasid', 'paosfi', 'sec']
mwecs4sa

mwecs4sa3#

下面将把您的输入字符串“解析”成由非单词字符分隔的“单词”字符序列。

String input = ...
String[] parts = input.split("[^\w]*");

我不知道你要怎么区分一张单子和胡言乱语。我想你需要再解释一下你的问题领域。。。
编辑:如果你不能定义你(作为一个人)用来区分列表和胡言乱语的规则,那么这个问题基本上是无法解决的。计算机不会变魔术你知道。。。
也许你应该用这个程序来处理那些“绝对”列表的子集,然后手工对其他列表进行分类。

cbeh67ev

cbeh67ev4#

要么你知道你的单词词典,要么你有一个列表分隔符的优先顺序。否则,这个问题的定义太模糊,计算机无法处理。
我想你的优先顺序可以是逗号,点,连字符,空格。所以,这意味着你用逗号来分开,而不是用点来分开等等。
或者,您可以继续按每个连续的分隔符进行拆分,直到找到不在文本中的分隔符。

qpgpyjmq

qpgpyjmq5#

如果你不能定义你的数据(“单词可以是任何东西,我没有办法事先知道字典里的任何单子可以包含什么。他们将不仅仅是数字。。。它可能是一个清单什么“),然后你有严重的问题。
具体来说,如果你不能定义你的数据,你的问题就无法解决。
你可以试试玩nltk。
你也许可以抛弃“杂音词”(“,”,“,”,“,”我“,”开始“,”用“,”然后“,”做“,”等)剩下的可能就是这个不可定义的“词可以是任何”剩下的。
除非你能更好地定义你的数据,否则你可能注定要付出很多努力。

bz4sfanl

bz4sfanl6#

解决这个问题的第一步是详细分析人类是如何解决这个问题的。我把这个问题分成两部分。
人类如何区分列表和非列表?例如,是不是因为非列表是符合语法的英语句子?如果是这样的话,您可以使用一个可用的自然语言处理工具包来区分列表和非列表。
人类如何识别列表中的分隔符和列表元素?例如,他们是否因为某些特定的领域知识而识别列表元素?或者他们只认识一小部分常用分隔符中的一个?列表元素总是单个单词吗?如果不是,在什么情况下是多个词?
我还将仔细查看几百个示例,看看是否有任何可以轻松识别和解析的常见模式。例如,如果30%的条目是简单的逗号分隔列表,那么正则表达式将很容易地识别和解析它们。也许一个小的正则表达式集可以处理大部分的语料库。
最后,我假设当前数据不仅被人类输入和识别,而且被人类消费。您将项目分解为列表的原因是为了从循环中删除人员,还是仅仅为了让他们的工作更轻松?如果是后者,我建议为它们提供分解列表元素,并作为备份,提供最初输入的文本。换言之,对冲你的赌注,以防你做错了。

j13ufse2

j13ufse27#

在java中,字符串标记器将执行此操作(即stringtokenizer(inputstring,delimiterlist))

StringTokenizer st = new StringTokenizer( "A B|C-D", " |-" );
while ( st.hasMoreTokens() ) {
    System.out.println( st.nextToken() );
}

印刷品

b
c
d

eulz3vhy

eulz3vhy8#

与其关注代码,不如关注方法。根据斯维尔登的话。。。
如果您的列表被用户使用,您可以要求他们在您出错时更正您的列表(此更正对输入文本的用户或以后查看文本的用户可见)。如果一个给定的输入看起来很像一个列表,但还不足以确定,你可以给他们看列表和原始输入,让他们选择。
要将输入自动分类为列表或文本,您可以创建几个度量标准来作为决策依据:
给定分隔符(即 [' ', '\t', ',', '.', 'and'] )这个短语用多少?期待一两个。哪一个?
是由片段组成的输入(使用某种语法系统)-片段倾向于表示列表。
此输入字段(或输入中的上下文)是否倾向于包含列表项
列表中的单词本身(有些单词可能总是表示您所在域中的一个句子或列表)
然后将这些信息传递到贝叶斯过滤器中,并使用用户的建议对其进行训练。我提到的大多数条目都会被转换成特殊的“关键字”,在将条目传递到过滤器之前,您可以使用这些关键字对其进行标记。如果筛选器有明确的答案,请将其视为列表或字符串。如果过滤器不确定,询问用户并使用他们的答案来训练过滤器。
编辑
您可以通过首先使用现有脚本对列表进行分类,然后手动检查列表来手动培训系统(即不向用户公开系统)。获取一个包含500个输入的列表,运行一个过滤器查找,或者其他简单的列表,并将它们分类为列表。训练贝叶斯过滤器对那些(与所有其他非列表),然后检查输出的手为所有500进一步培训。
每天都有人会收到一封电子邮件,上面写着当天所有的边缘案例,必要时可以点击邮件中的链接来修正系统。
作为一个附带问题(与op评论有关),一般来说,贝叶斯滤波器比神经网络更易于实现、调试、测试、分析和扩展。

2o7dmzc5

2o7dmzc59#

从谷壳里筛出小麦来。。。

rawdata = """\
one, two, three, four, five
one. two. three, four. five.
"I start with one, then do two, maybe three and four then five"
one  
two  
three  
four  
five.  
one, two. three four five
one two three four - five
"not even a list, no list-elements here! but list item separators may appear. grrr"
a dog with a bone is a beautiful twosome""".splitlines()

from pyparsing import oneOf, WordStart, CharsNotIn, alphas, LineEnd
options = (WordStart() + oneOf("one two three four five") + (CharsNotIn(alphas)|LineEnd()))

for userinput in rawdata:
    print userinput
    print [opt[0] for opt in options.searchString(userinput)]
    print

打印(请注意,添加的行中隐藏了“one”和“two”子字符串,这是不需要的):

one, two, three, four, five
['one', 'two', 'three', 'four', 'five']

one. two. three, four. five.
['one', 'two', 'three', 'four', 'five']

"I start with one, then do two, maybe three and four then five"
['one', 'two', 'three', 'four', 'five']

one  
['one']

two  
['two']

three  
['three']

four  
['four']

five.  
['five']

one, two. three four five
['one', 'two', 'three', 'four', 'five']

one two three four - five
['one', 'two', 'three', 'four', 'five']

"not even a list, no list-elements here! but list item separators may appear. grrr"
[]

a dog with a bone is a beautiful twosome
[]

相关问题