在这里记录一下关于软件构造课程Lab3中关于正则表达式的应用。

  在实验内容中,要求用正则表达式来匹配读入文件的内容,从而取得构建图需要的相关信息。

  举个例子,读入的文件(GraphPoetTestFile.txt)内容如下:

  先说一下文件内容中的数据格式:

  ①一定有一行,第一个单词为"GraphType",后面是一个空格、一个'='、一个空格,加上一个"类型名"

  ②一定有一行,第一个单词为"GraphName",后面是一个空格、一个'='、一个空格,加上一个"图的名字"

  ③一定有一行,第一个单词为"VertexType"/"EdgeType",后面是一个空格、一个'='、一个空格,加上若干个"顶点类型",不同顶点类型之间用','和空格隔开

  ④一定有若干行,第一个单词为"Vertex",后面是一个空格,一个'='、一个空格、一个左尖括号'<',加上若干个"数据信息",最后用右尖括号'>'结束(中间可能仍有尖括号来界定属性信息)

  ⑤一定有若干行,第一个单词为"Edge",后面是一个空格,一个'='、一个空格、一个左尖括号'<',加上若干个"数据信息",信息项之间用','和空格隔开,最后用右尖括号'>'结束

  ⑥可能存在若干行,第一个单词为"HyperEdge",后面是一个空格,一个'='、一个空格、一个左尖括号'<',加上若干个"数据信息",信息项之间用','和空格隔开,包含一组大括号'{''}'来界定的属性信息,最后用右尖括号'>'结束

  下面说一下对于这个问题而言,我的解决思路:

  首先,分析读入文件的格式,每一行读入引号中的数据项个数可能不一致,有的行只包含一项,有的行却包含多项,因此没有一种完美的正则表达式能直接全部读取所有引号的数据项。同时,考虑到还有尖括号'<>'以及大括号'{}'来界定的情况,这种直接构建完整正则表达式进行匹配的方式似乎不存在或者说使用情况比较复杂。

  先说明两种基本的匹配字符串的方式,一种是最大化地进行匹配字符串,一种是最小化地进行匹配字符串。

  比如,对于一个字符串/Introduction = "I", "Am", "Steven", "Shen"/(这里用'/'来表示字符串界定符以避免产生歧义),最大化地进行匹配的话,我要得到的就是引号区间界定的整个字符串匹配,即/"I", "Am", "Steven", "Shen"/;最小化地进行匹配的话,我要得到的就是引号区间界定的一小部分字符串匹配,即/I/,再次重复进行匹配就会依次得到/Am/、/Steven/、/Shen/。这两种正则表达式在Java中的具体字符串表示格式就是max = "(\".+\")",min = "\"([^\"]+)\""。

  下面回到问题上来,我的解决思路有两种:

  第一种方式,通过max和min的使用,细致化地获取数据

  对每一行先进行这样的匹配String pattern1 = "(\\w+) = (\".+\")"; 即每行先是一个单词,一个空格,一个'=',一个空格,后加一个max型的匹配,得到'='后所有信息项。匹配上面的那个文件,第一行匹配结果就是/GraphType/、/"MovieGraph"/,第三行匹配结果就是/VertexType/、/"Movie", "Actor", "Director"/。此时,我们判断第一个读入的单词的内容,即可确定该如何处理'='后面的信息项。此时再对第二个获取的串(通过max匹配得到的串)进行最小化地匹配,第一行就得到了/MovieGraph/,第三行就得到了/Movie/、/Actor/、/Director/三个项。类似地,把界定范围改成尖括号内的内容,同样也可以获取Vertex以及Edge的信息。

  这种解决方式总的思路就是通过匹配每行第一个单词来确定如何处理这行数据'='后的数据项。然后通过最大化地匹配'='后的数据,进一步对其用最小化匹配进行划分,得到具体的数据项。

  第二种方式,通过max的使用,结合对字符串的操作达成目标

  类似于上面说的,得到每行第一个单词后,用最大化匹配来得到'='后的数据项,此时匹配的内容就是/"I", "Am", "Steven", "Shen"/,然后对这个字符串使用String的split方法(当然,split的参数列表实际上接收的就是一个正则表达式的字符串)。这里的split方法就是这样split(",\\s")。这样,/"I", "Am", "Steven", "Shen"/就变成了/"I"/、/"Am"/、/"Steven"/、/"Shen"/,他们存储在一个String数组中,这时还要数组中每个串求子串,从而去掉每个串两端的引号(")。即通过String的subString方法,得到/I/、/Am/、/Steven/、/Shen/。

  这种解决方式总的思路就是先获取要读取的数据块,在对数据块用String的操作来完成每个需要读取的数据项。这种方式相比于前面那种比较麻烦,原因在于求子串、分割过程比较繁琐,不如上面那种方法的用最小化匹配方便快捷。

  这两种方法的正则表达式匹配串并获取,都用到了group方法,这些内容在Java的String和正则表达式部分都有详细介绍,这里就不再赘述了。

  至于文件中可能存在的匹配不同界定符的情况,可以类似地考虑如何实现。主要思路就在上面,具体实现时可以通过每行数据项的个数等确定性信息来进行信息读取,使得处理更灵活。

  下面附上针对这种MovieGraph的处理代码。  

 package factory;

 import java.util.*;
import java.util.regex.*;
import java.io.*;
import vertex.*;
import edge.*;
import graph.*; public class MovieGraphFactory {
public static MovieGraph createGraph(String filePath) {
String GraphType = "";
String GraphName = "";
String VertexType = "";
List<String> VertexTypes = new ArrayList<>();
String EdgeType = "";
List<String> EdgeTypes = new ArrayList<>();
Set<String> fullVertexInfo = new HashSet<>();
Set<String> fullEdgeInfo = new HashSet<>();
Set<String> fullHyperEdgeInfo = new HashSet<>();
List<Vertex> vertexList = new ArrayList<>();
List<Edge> edgeList = new ArrayList<>();
List<Edge> hyperList = new ArrayList<>();
String pattern1 = "(\\w+) = (\".+\")";
String pattern2 = "(\\w+) = <(.+)>";
String pattern3 = ",? ?\"([^\"]+)\"";
Pattern p = Pattern.compile(pattern1);
Matcher parse1 = p.matcher("");
p = Pattern.compile(pattern2);
Matcher parse2 = p.matcher("");
MovieGraph graph = null;
try {
File file = new File(filePath);
InputStreamReader readin = new InputStreamReader(new FileInputStream(file));
BufferedReader bufReadin = new BufferedReader(readin);
String line;
int i = 1;
while((line = bufReadin.readLine()) != null) {
parse1.reset(line);
parse2.reset(line);
if(parse1.find()) {
if(parse1.groupCount() == 2) {
if(parse1.group(1).equals("GraphType")) {
GraphType = parse1.group(2);
if(!GraphType.equals("\"MovieGraph\"")) {
System.out.println("Error! the graph must be MovieGraph rather be " + GraphType);
bufReadin.close();
throw new RuntimeException();
}
}
if(parse1.group(1).equals("GraphName"))
GraphName = parse1.group(2);
if(parse1.group(1).equals("VertexType"))
VertexType = parse1.group(2);
if(parse1.group(1).equals("EdgeType"))
EdgeType = parse1.group(2);
}
} else if(parse2.find()) {
if(parse2.groupCount() == 2) {
if(parse2.group(1).equals("Vertex"))
fullVertexInfo.add(parse2.group(2));
if(parse2.group(1).equals("Edge"))
fullEdgeInfo.add(parse2.group(2));
if(parse2.group(1).equals("HyperEdge"))
fullHyperEdgeInfo.add(parse2.group(2));
}
}
}
p = Pattern.compile(pattern3);
Matcher parse3 = p.matcher(GraphType);
if(parse3.find())
GraphType = parse3.group(1);
parse3 = p.matcher(GraphName);
if(parse3.find())
GraphName = parse3.group(1);
parse3 = p.matcher(VertexType);
while(parse3.find()) {
VertexTypes.add(parse3.group(1));
}
parse3 = p.matcher(EdgeType);
while(parse3.find()) {
EdgeTypes.add(parse3.group(1));
} String label = "", type = "";
String[] fields = null; for(String temp : fullVertexInfo) {
i = 0;
Vertex point = null;
parse3 = p.matcher(temp);
if(parse3.find())
label = parse3.group(1);
if(parse3.find()) {
type = parse3.group(1);
}
switch(type) {
case "Actor" :
fields = new String[2];
break;
case "Director" :
fields = new String[2];
break;
case "Movie" :
fields = new String[3];
break;
default :
System.out.println("Error. The graph can't contain other vertex " + type);
bufReadin.close();
throw new RuntimeException();
}
while(parse3.find()) {
fields[i++] = parse3.group(1);
}
switch(type) {
case "Actor" :
point = ActorVertexFactory.createVertex(label, fields);
break;
case "Director" :
point = DirectorVertexFactory.createVertex(label, fields);
break;
case "Movie" :
point = MovieVertexFactory.createVertex(label, fields);
break;
default :
break;
}
vertexList.add(point);
} for(String temp : fullEdgeInfo) {
parse3 = p.matcher(temp);
Double weight = 0.0;
Vertex point1 = null, point2 = null;
Edge edge = null;
if(parse3.find())
label = parse3.group(1);
if(parse3.find())
type = parse3.group(1);
if(parse3.find())
weight = Double.parseDouble(parse3.group(1));
if(parse3.find())
for(Vertex start : vertexList) {
if(parse3.group(1).equals(start.getLabel())) {
point1 = start;
break;
}
}
if(parse3.find())
for(Vertex end : vertexList) {
if(parse3.group(1).equals(end.getLabel())) {
point2 = end;
break;
}
}
if(parse3.find())
if(!parse3.group(1).equals("No")) {
bufReadin.close();
throw new RuntimeException();
}
List<Vertex> arg = new ArrayList<>();
arg.add(point1); arg.add(point2);
switch(type) {
case "MovieActorRelation" :
edge = MovieActorRelationFactory.createEdge(label, arg, weight);
break;
case "MovieDirectorRelation" :
edge = MovieDirectorRelationFactory.createEdge(label, arg, -1.0);
break;
default :
System.out.println("Error, the graph can't contain other edge " + type);
bufReadin.close();
throw new RuntimeException();
}
edgeList.add(edge);
} for(String temp : fullHyperEdgeInfo) {
parse3 = p.matcher(temp);
Edge hyper = null;
if(parse3.find()) {
label = parse3.group(1);
}
if(parse3.find())
type = parse3.group(1);
List<Vertex> hyperVertices = new ArrayList<>();
while(parse3.find()) {
for(Vertex temppoint : vertexList) {
if(parse3.group(1).equals(temppoint.getLabel())) {
hyperVertices.add(temppoint);
break;
}
}
}
hyper = SameMovieHyperEdgeFactory.createEdge(label, hyperVertices, -1.0);
hyperList.add(hyper);
} graph = new MovieGraph(GraphName);
for(Vertex temp : vertexList) {
graph.addVertex(temp);
}
for(Edge temp : edgeList) {
graph.addEdge(temp);
}
for(Edge temp : hyperList) {
graph.addEdge(temp);
} System.out.println("***** vertexList's length : " + vertexList.size());
System.out.println("***** edgeList's length : " + edgeList.size());
System.out.println("***** hyperList's length : " + hyperList.size());
System.out.println("Vertex:" + fullVertexInfo.size()+ "\n" + fullVertexInfo + "\n" + "Edge:" + fullEdgeInfo.size() + "\n" + fullEdgeInfo + "\n" + "HyperEdge:" + fullHyperEdgeInfo.size() + "\n" + fullHyperEdgeInfo);
bufReadin.close();
} catch(Exception e) {
e.printStackTrace();
}
return graph;
}
}

MovieGraphFactory.java

  思路比较简单,事实证明可行。代码写得不高端...

  见证菜鸡成长...

  

关于Lab3中对于正则表达式的应用的更多相关文章

  1. PHP中有关正则表达式的函数集锦

    之前学正则表达式的目的是想从网上抓取点小说啊,文档啊,还有获取相应的视频连接然后批量下载.当时初学PHP根本不知道PHP有专门抓包的工具,就像Simple_html_dom.php(在我的其他博文中有 ...

  2. JavaScript中的正则表达式(终结篇)

    JavaScript中的正则表达式(终结篇) 在之前的几篇文章中,我们了解了正则表达式的基本语法,但那些语法不是针对于某一个特定语言的.这篇博文我们将通过下面几个部分来了解正则表达式在JavaScri ...

  3. Coursera-Getting and Cleaning Data-week4-R语言中的正则表达式以及文本处理

    博客总目录:http://www.cnblogs.com/weibaar/p/4507801.html Thursday, January 29, 2015 补上第四周笔记,以及本次课程总结. 第四周 ...

  4. 9.JAVA中的正则表达式

    一.JAVA中的正则表达式 1.概念:以某种特定的方式描述字符串 1.Java中正则表达式的规则 ?          #{0,1}-?有一个-或者没有 \\           #表示一个" ...

  5. Python::re 模块 -- 在Python中使用正则表达式

    前言 这篇文章,并不是对正则表达式的介绍,而是对Python中如何结合re模块使用正则表达式的介绍.文章的侧重点是如何使用re模块在Python语言中使用正则表达式,对于Python表达式的语法和详细 ...

  6. 工作随笔——UIButton的EdgeInsets + Swift中的正则表达式;

    1.UIButton的EdgeInsets UIButton的EdgeInsets方法,是用来设置title和image对于上左下右四个方向的偏移,但是很奇怪的是,刚开始只有Image,titile也 ...

  7. Javascript中的正则表达式

    Javascript中的正则表达式 刚开始接触正则表达式的时候,觉得这是个很死板的东西(没办法,计算机不能像人眼一样能很快的辨认出我们需要的结果,它需要一定的规则来对它进行限制),了解的越多,发现这个 ...

  8. 在Visual Studio中使用正则表达式匹配换行和批量替换

    系统环境:Windows 8.1 Enterprise Update 2 x64 开发环境:Mircosoft Visual Studio Ultimate 2013 Update 2 RC 问题:如 ...

  9. 浅谈JavaScript中的正则表达式

    引言 对于正则表达式我想作为程序员肯定使用过它,那天书般的表达方式,我用一次就记住它了.这篇博客先介绍一些正则表达式的内容,然后介绍JavaScript中对正则表达式特有的改进.下面开始介绍正则表达式 ...

随机推荐

  1. acm数论之旅---扩展欧几里得算法

    度娘百科说: 首先, ax+by = gcd(a, b) 这个公式肯定有解 (( •̀∀•́ )她说根据数论中的相关定理可以证明,反正我信了) 所以 ax+by = gcd(a, b) * k 也肯定 ...

  2. flask_migrate

    flask_migrate 1.      flask_migrate doc: https://flask-migrate.readthedocs.io/en/latest/ 1.1.    简介 ...

  3. windows和ubuntu安装以太坊客户端Mist

    Mist钱包下载地址:https://github.com/ethereum/mist/releases Mist = Ethereum Wallet + Web3 浏览器 Dapp:bancor 史 ...

  4. Java学习资源 - 测试

    JUnit注解解释 1. @Test : 测试方法,测试程序会运行的方法,后边可以跟参数代表不同的测试,如(expected=XXException.class) 异常测试,(timeout=xxx) ...

  5. HDU1875 畅通工程再续

    相信大家都听说一个“百岛湖”的地方吧,百岛湖的居民生活在不同的小岛中,当他们想去其他的小岛时都要通过划小船来实现.现在政府决定大力发展百岛湖,发展首先要解决的问题当然是交通问题,政府决定实现百岛湖的全 ...

  6. ANSYS-APDL施加扭转载荷CERIG命令

    目录 1. 要求 2. ANSYS有限元分析 2.1 APDL建模 2.2 APDL施加载荷 2.3 APDL查看结果 3. 举一反三 1. 要求 一块0.8m*0.4m*0.04m厚的钢板,在板的两 ...

  7. Myeclipse下PHP开发环境搭建及运行

    外接CSDN链接 http://blog.csdn.net/yuxiangaaaaa/article/details/54948426 这是php初始设置,后面进行重新设置

  8. Update(Stage4):sparksql:第3节 Dataset (DataFrame) 的基础操作 & 第4节 SparkSQL_聚合操作_连接操作

    8. Dataset (DataFrame) 的基础操作 8.1. 有类型操作 8.2. 无类型转换 8.5. Column 对象 9. 缺失值处理 10. 聚合 11. 连接 8. Dataset ...

  9. vue 和 jquery混合使用

    有时候只要想到要用的 vue.js 的时候就会惯性的想起用vue-cli手脚架搭建一个项目,但是有时候的业务场景并不适合用vue-cli手脚架,这个时候使用vue+jquery混合使用,把他们的优点结 ...

  10. git分支在项目中管理

    实际项目中如何使用Git做分支管理 2018年06月24日 18:08:24 ShuSheng007 阅读数:9241   版权声明: https://blog.csdn.net/ShuSheng00 ...