之前的软件设计与开发实践课程中,自己构思的大作业题目。做的具有核心功能,但是还欠缺边边角角的小功能和持久化数据结构,先放出来,有机会一点点改。github:https://github.com/chuxiuhong/smarteditor

数据结构,使用过程截图以及源代码如下:

#数据结构

**trie树**

trie树相应的介绍点击链接 https://en.wikipedia.org/wiki/Trie

trie树在python文件中的类型定义

Node定义

#GUI设计界面

首先,用较大的文本文件进行训练,完成trie的树的训练。本文件夹下提供了一个big2.txt文件作为示例。


在之后的输入会弹出提示框

  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. import PyQt4
  4. from PyQt4.QtCore import *
  5. from PyQt4.QtGui import *
  6. import PyQt4.QtCore
  7. import sys
  8. import pickle
  9.  
  10. print '===================start======================='
  11.  
  12. class Node:
  13. def __init__(self):
  14. self.value = None
  15. self.children = {} # children is of type {char, Node}
  16. self.fre = 0
  17. self.father = None
  18.  
  19. def CMP(a, b):
  20. return b.fre - a.fre
  21.  
  22. class Trie:
  23. def __init__(self):
  24. self.root = Node()
  25. self.choose = []
  26. self.__OpenCorrect__ = 0
  27.  
  28. def insert(self, key): # key is of type string
  29. # key should be a low-case string, this must be checked here!
  30. node = self.root
  31. for char in key:
  32. if char not in node.children:
  33. child = Node()
  34. node.children[char] = child
  35. child.value = char
  36. child.father = node
  37. node = child
  38. else:
  39. node = node.children[char]
  40. # node.value = key
  41. node.fre += 1
  42.  
  43. def search(self, key):
  44. node = self.root
  45. for char in key:
  46. if char not in node.children:
  47. return None
  48. else:
  49. node = node.children[char]
  50. return node.value
  51.  
  52. def display_node(self, node):
  53. if (node.value != None):
  54. print node.value
  55. for char in 'abcdefghijklmnopqrstuvwxyz':
  56. if char in node.children:
  57. self.display_node(node.children[char])
  58. return
  59.  
  60. def fallback(self, node):
  61. f_char = ''
  62. while node != self.root:
  63. f_char = node.value + f_char
  64. node = node.father
  65. # print f_char
  66. return f_char
  67.  
  68. def display(self):
  69. self.display_node(self.root)
  70.  
  71. def find_node(self, string):
  72. res_node = self.root
  73. for i in string:
  74. res_node = res_node.children[i]
  75. return res_node
  76.  
  77. def association(self, node):
  78. # 调用此函数前应该先将self.choose恢复成空列表
  79. if (node.value != None):
  80. if node.fre > 0:
  81. self.choose.append(node)
  82. for char in 'abcdefghijklmnopqrstuvwxyz':
  83. if char in node.children:
  84. self.association(node.children[char])
  85.  
  86. def output_association(self, char):
  87. char = str(char).lower()
  88. self.choose = []
  89. result_list = []
  90. self.association(self.find_node(char))
  91. self.choose.sort(cmp=CMP)
  92. if len(self.choose) > 0:
  93. for i in self.choose:
  94. result_list.append(self.fallback(i))
  95. if self.__OpenCorrect__ == 0:
  96. result_list.insert(1, self.correct(char))
  97. # print 'result_list',result_list
  98. return result_list
  99.  
  100. def correct(self, string):
  101. self.choose = []
  102. p = self.find_node(string[:-1])
  103. self.association(p)
  104. self.choose.sort(cmp=CMP)
  105. if len(self.choose) > 1:
  106. return self.fallback(self.choose[0])
  107.  
  108. def train(trie, path):
  109. # f = open(r'big2.txt')
  110. f = open(path)
  111. word = f.read()
  112. f.close()
  113. word = word.split(' ')
  114. for i in word:
  115. trie.insert(i)
  116.  
  117. trie = Trie()
  118. trie.__OpenCorrect__ = 0
  119.  
  120. def save_model(T):
  121. f1 = open("trie.pkl", 'wb')
  122. pickle.dump(T, f1)
  123. f1.close()
  124.  
  125. def load_model(path):
  126. f2 = open(path, 'rb')
  127. trie = pickle.load(f2)
  128. f2.close()
  129.  
  130. print '================= END ====================='
  131.  
  132. class UI(QDialog):
  133. def __init__(self, parent=None):
  134. super(UI, self).__init__(parent)
  135. QSList = QStringList()
  136. # default
  137. # QSList<<'One'<<'Tow'<<'Three'<<'Four'<<'Five'
  138. # instance of Completer class
  139. cmp = Completer(QSList)
  140. global edit
  141. edit = TextEdit()
  142. edit.setFontPointSize(80)
  143. edit.setCompleter(cmp)
  144. self.setWindowTitle(u"智能文本编辑器")
  145. button1 = QPushButton(u"训练模型")
  146. button2 = QPushButton(u"保存文本文件")
  147. button3 = QPushButton(u"打开文本文件")
  148. '''
  149. buttons = QushButton()
  150. '''
  151. '''
  152. 定义按钮,()内为按钮名称
  153. '''
  154. self.connect(button1, SIGNAL("clicked()"), self.get_file)
  155. self.connect(button2, SIGNAL("clicked()"), self.func2)
  156. self.connect(button3, SIGNAL("clicked()"), self.func3)
  157. '''
  158. 关联按钮与函数格式同上,触发为clicked()单击,最后一个参数为
  159. 类内函数
  160. '''
  161. layout = QGridLayout()
  162. layout.addWidget(edit, 0, 1, 1, 5)
  163. layout.addWidget(button1, 2, 1)
  164. layout.addWidget(button2, 2, 3)
  165. layout.addWidget(button3, 2, 5)
  166. '''
  167. 按钮布局
  168. '''
  169. self.setLayout(layout)
  170. self.center()
  171.  
  172. def center(self):
  173. screen = QDesktopWidget().screenGeometry()
  174. size = self.geometry()
  175. self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2)
  176.  
  177. def get_file(self):
  178. s = QFileDialog.getOpenFileName(self, "Open file dialog", "/", "TXT Files(*.txt)")
  179. train(trie, s)
  180.  
  181. def func2(self):
  182. s = QFileDialog.getSaveFileName(self, "文件保存", "C:/", "All Files (*);Text Files (*.txt)")
  183. f = open(s, 'w')
  184. f.write(edit.toPlainText())
  185. f.close()
  186.  
  187. def func3(self):
  188. s = QFileDialog.getOpenFileName(self, "Open file dialog", "/", "TXT Files(*.txt)")
  189. f = open(s)
  190. edit.setText(PyQt4.QtCore.QString(f.read()))
  191. f.close()
  192.  
  193. class TextEdit(QTextEdit):
  194. def __init__(self, parent=None):
  195. super(TextEdit, self).__init__(parent)
  196. self.cmp = None
  197. self.p = ''
  198. self.count = 0
  199.  
  200. def setCompleter(self, completer):
  201. if self.cmp:
  202. self.disconnect(self.cmp, 0, 0)
  203. self.cmp = completer
  204. if (not self.cmp):
  205. return
  206. self.cmp.setWidget(self)
  207. self.cmp.setCompletionMode(QCompleter.PopupCompletion)
  208. self.cmp.setCaseSensitivity(Qt.CaseInsensitive)
  209. self.connect(self.cmp, SIGNAL('activated(QString)'), self.insertCompletion)
  210.  
  211. def completer(self):
  212. return self.cmp
  213.  
  214. def insertCompletion(self, string):
  215.  
  216. # get cursor position
  217. tc = self.textCursor()
  218. # selectd ranges
  219. tc.movePosition(QTextCursor.StartOfWord, QTextCursor.KeepAnchor)
  220.  
  221. # replace selected ranges
  222. tc.insertText(string)
  223. self.p += str(string)
  224. # set cursor pos back to original pos
  225. self.setTextCursor(tc)
  226.  
  227. def textUnderCursor(self):
  228. tc = self.textCursor()
  229. tc.select(QTextCursor.WordUnderCursor)
  230. return tc.selectedText()
  231.  
  232. def keyPressEvent(self, e):
  233. '''
  234. if e.key() != Qt.Key_Backspace:
  235. self.p = self.p + e.text()
  236. self.count+=1
  237. print 'yes'
  238. else:
  239. self.p = self.p[:-1]
  240. self.count-=1
  241. '''
  242. print 'p ', self.p
  243. print 'pressed >> ', e.text()
  244. if (self.cmp and self.cmp.popup().isVisible()):
  245. if e.key() in (Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape, Qt.Key_Tab, Qt.Key_Backtab):
  246. e.ignore()
  247. return
  248.  
  249. isShortcut = ((e.modifiers() & Qt.ControlModifier) and e.key() == Qt.Key_E)
  250. if (not self.cmp or not isShortcut):
  251. super(TextEdit, self).keyPressEvent(e)
  252.  
  253. ctrlOrShift = e.modifiers() & (Qt.ControlModifier | Qt.ShiftModifier)
  254. if (not self.cmp or (ctrlOrShift and e.text().isEmpty())):
  255. return
  256.  
  257. eow = QString("~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-=")
  258. hasModifier = (e.modifiers() != Qt.NoModifier) and not ctrlOrShift
  259. completionPrefix = self.textUnderCursor()
  260. # hide popup while matching invalid cases
  261. if (not isShortcut and (hasModifier or e.text().isEmpty() or completionPrefix.length() < 1
  262. or eow.contains(e.text().right(1)))):
  263. self.cmp.popup().hide()
  264. return
  265.  
  266. self.cmp.update(completionPrefix)
  267. self.cmp.popup().setCurrentIndex(self.cmp.completionModel().index(0, 0))
  268.  
  269. cr = self.cursorRect()
  270. cr.setWidth(self.cmp.popup().sizeHintForColumn(0)
  271. + self.cmp.popup().verticalScrollBar().sizeHint().width())
  272. word = self.p.split(' ')[:-1]
  273. self.p = ''
  274. for k in xrange(len(word)):
  275. self.p += word[k]
  276. print 'self.p=', self.p
  277. self.cmp.complete(cr)
  278.  
  279. class Completer(QCompleter):
  280. def __init__(self, stringlist, parent=None):
  281. super(Completer, self).__init__(parent)
  282. self.stringlist = stringlist
  283. self.setModel(QStringListModel())
  284.  
  285. # update function will trigger while the text has been modified
  286. def update(self, completionText):
  287. # generate a new QStringList instance
  288. qsList = QStringList()
  289.  
  290. # generate hint lists which returns by customatic definitions
  291. newList = genMyStrList(completionText)
  292. for item in newList:
  293. qsList.append(item)
  294.  
  295. self.stringlist = qsList
  296. # filteredList = self.stringlist.filter(completionText, Qt.CaseInsensitive)
  297. self.model().setStringList(self.stringlist)
  298. self.popup().setCurrentIndex(self.model().index(0, 0))
  299.  
  300. # the function below defined a way to generate a string list
  301. def genMyStrList(key):
  302. my_str_list = trie.output_association(key)
  303. return my_str_list
  304.  
  305. def main():
  306. app = QApplication(sys.argv)
  307. app.processEvents()
  308. form = UI()
  309. form.show()
  310. # splash.finish(form)
  311. app.exec_()
  312. window = QMainWindow()
  313. window.statusBar().showMessage('Yuan Ziqi')
  314. menubar = window.menuBar
  315.  
  316. window.setWindowTitle('Auto Complete Demo')
  317. window.resize(400, 200)
  318. window.move(400, 100)
  319.  
  320. edit = TextEdit()
  321. edit.setFontPointSize(40)
  322. edit.setCompleter(cmp)
  323. # bt = addbutton()
  324. # window.addDockWidget(bt)
  325. window.setCentralWidget(edit)
  326. window.show()
  327. sys.exit(app.exec_())
  328.  
  329. if __name__ == '__main__':
  330. print 'app is running successfully'
  331. main()

基于trie树的具有联想功能的文本编辑器的更多相关文章

  1. 基于trie树做一个ac自动机

    基于trie树做一个ac自动机 #!/usr/bin/python # -*- coding: utf-8 -*- class Node: def __init__(self): self.value ...

  2. 用trie树实现输入提示功能,输入php函数名,提示php函数

    参照刘汝佳的trie树 结构体 #include "stdio.h" #include "stdlib.h" #include "string.h&q ...

  3. [转] Trie树详解及其应用

    一.知识简介         最近在看字符串算法了,其中字典树.AC自动机和后缀树的应用是最广泛的了,下面将会重点介绍下这几个算法的应用.       字典树(Trie)可以保存一些字符串->值 ...

  4. Trie树详解及其应用

    一.知识简介        最近在看字符串算法了,其中字典树.AC自动机和后缀树的应用是最广泛的了,下面将会重点介绍下这几个算法的应用.      字典树(Trie)可以保存一些字符串->值的对 ...

  5. Trie树也称字典树

    Trie树 Trie树也称字典树,因为其效率很高,所以在在字符串查找.前缀匹配等中应用很广泛,其高效率是以空间为代价的. 一.Trie树的原理 利用串构建一个字典树,这个字典树保存了串的公共前缀信息, ...

  6. LeetCode Implement Trie (Prefix Tree) (实现trie树3个函数:插入,查找,前缀)

    题意:实现trie树的3个功能,只含小写字母的串. 思路:老实做即可! class TrieNode { public: TrieNode* chd[]; bool flag; // Initiali ...

  7. Trie 树(转)

    看了很多 Trie 树的介绍, 这篇讲的最好,简单易懂(特别是代码部分),直接转载:http://www.cnblogs.com/dolphin0520/archive/2011/10/11/2207 ...

  8. 【动画】看动画轻松理解「Trie树」

    Trie树 Trie这个名字取自“retrieval”,检索,因为Trie可以只用一个前缀便可以在一部字典中找到想要的单词. 虽然发音与「Tree」一致,但为了将这种 字典树 与 普通二叉树 以示区别 ...

  9. Trie树(Prefix Tree)介绍

    本文用尽量简洁的语言介绍一种树形数据结构 -- Trie树. 一.什么是Trie树 Trie树,又叫字典树.前缀树(Prefix Tree).单词查找树 或 键树,是一种多叉树结构.如下图: 上图是一 ...

随机推荐

  1. Java 字符串格式化详解

    Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...

  2. ASP.NET Core project.json imports 是什么意思?

    示例代码: "frameworks": { "netcoreapp1.0.0": { "imports" : "portable- ...

  3. Mybatis XML配置

    Mybatis常用带有禁用缓存的XML配置 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE ...

  4. UVA-146 ID Codes

    It is 2084 and the year of Big Brother has finally arrived, albeit a century late. In order to exerc ...

  5. 简单分析JavaScript中的面向对象

    初学JavaScript的时候有人会认为JavaScript不是一门面向对象的语言,因为JS是没有类的概念的,但是这并不代表JavaScript没有对象的存在,而且JavaScript也提供了其它的方 ...

  6. 【干货分享】流程DEMO-采购预算编制

    流程名: 采购预算编制  业务描述: 在月初由计财部进行预算编辑,提交审批后预算生效  流程相关文件: 流程包.xml WebService业务服务.xml WebService.asmx WebSe ...

  7. IOS之Objective-C学习 ARC下的单例模式

    单例模式是我常用的一种设计模式,最常见的用途就是用来保存数据并且传递数据.这都归功于单例模式的特性,首先就让我为大家简单介绍一下单例模式的特性. 单例模式的三大特性: 1.某个类只能有一个实例: 2. ...

  8. Java企业实训 - 01 - Java前奏

    前言: 虽然个人专攻.NET方向,不过由于个人是干教育行业的,方方面面的东西,不能说都必须精通,但肯定多少都会涉及到. 一个菜鸟学员,从啥都不会,经过一步步学习,最后到企业上手掌管一个模块甚至一个项目 ...

  9. MySQL加密

    MySQL字段加密和解密 1.加密:aes_encrypt('admin','key') 解密:aes_decrypt(password,'key') 2.双向加密 通过密钥去加密,解密的时候的只有知 ...

  10. join Linq

    List<Publisher> Publishers = new List<Publisher>(); Publisher publish1 = new Publisher() ...