单位提取的迭代程序

时间:2014-02-06 18:29:34

标签: regex clojure

有时会有一系列值后跟一个度量单位。输入将是一个包含数字的文本字符串,后跟要由函数提取的单位。给定一个包含数字后跟单位的文本字符串,以下内容可以将数字和单位提取为嵌套向量:

(def aa ["meter" "kilometer"])
(def bb (clojure.string/join "|" aa))
(def cc (str "(\\d+)\\s*(" bb ")")) 
(def dd (re-pattern  cc))

(defn foostring [strings]
     (into [] (map into [] (map (fn [[_ count unit]] {:count count, :unit unit})
     (re-seq dd strings)))))

例如,让我们尝试输入:

(foostring "Today I sprinted 40 meters.")

输出将是:

[[[:count 40] [:unit meter]]]

但是我无法提取一系列数字,后跟一个单位,例如以下示例:

(foostring "Today I sprinted between 80-90 meters.")

该功能将为计数和计量单位选择90。但是,我试图获取单位前面的数字范围。

我认为可以提取此类模式的想法将以“近邻”的形式递归查看。即,函数找到单位,然后在单位的左侧查找数字。在“向左看”的过程中,该功能可能搜索单个数字,例如所提到的例子,数字后跟标点符号,即斜线 - 或一个单词。扩展上一次搜索让我举一个例子:

(foostring "Today I ran between 80 to 90 meters.")

或者,口语

(foostring“有80 80 Yeti穿过森林。”)

虽然Yeti的例子很奇怪,但在写作时,它会捕捉到人们的语音被翻译成文本的想法。可能发生这种情况的一个例子是在引用某人撰写文章的过程中。

2 个答案:

答案 0 :(得分:3)

  

我认为可以提取此类模式的想法将以“近邻”的形式递归查看。

如果你的意思是递归,那么你肯定会离开正则表达式的领域。如果你对表达式不太疯狂,可以使用无上下文的EBNF。

(require '[instaparse.core :as insta])


(def foostring
  (insta/parser
     "<S> = Expr+
      Expr = <Stuff> Number+ {<[' '] [Preposition] [' ']> Number} <' '> Unit <Stuff>;
      Bleh = #'[a-z A-Z.,]+';
      Stuff = {Bleh}
      Preposition = 'between'|'to'|'-';
      Unit = 'meter'|'kilometer'|'Yeti'|'sandwiches';
      Number = #'[0-9]+'"))

如果您没有单位/介词的设定列表,请定义为例如任何一个字。

(foostring "Today I sprinted 40 meters while eating 2 3 4 sandwiches, running from 80-90 Yeti.")
=>
([:Expr [:Number "40"] [:Unit "meter"]]
 [:Expr [:Number "2"] [:Number "3"] [:Number "4"] [:Unit "sandwiches"]]
 [:Expr [:Number "80"] [:Number "90"] [:Unit "Yeti"]])

答案 1 :(得分:1)

试试这个:

(?i)(?<lowerBound>\d+)(?:\s*(?:-|to)\s*(?<upperBound>\d+))?\s+(?<unit>meters?|kilometers?|...)

描述

Regular expression visualization

演示

http://fiddle.re/k20ff (选择Java,因为Clojure与Java共享相同的风格)