选择包含任何顺序的子集字符的行

时间:2017-06-06 15:23:18

标签: postgresql

我有一个包含英语单词列表的表格,我试图从中选择所有可以使用给定字符串"hand"生成的单词(如游戏拼字游戏中所示)

+--------+
|  word  |
+--------+
| test   |
| father |
| woman  |
| zebra  |
+--------+

我到目前为止的查询只会检查单词中是否存在手中的任何字符。

SELECT * FROM words WHERE word SIMILAR to '%e%|%z%|%h%';
/* returns test, father and zebra as they all contain either e,z or h */

然而,这并没有考虑一个单词是否包含比手更多次的字符,我在python中使用的代码来检查一个单词是否有效

def isValidWord(word, hand):
    """Return true or false can the word be made using the characters in the hand"""
    for i in word: # for each character in word
        if hand.count(i)<word.count(i): # is the character in the hand enough times
            return False
    return True # if every character in the word is present in the hand

我的问题是如何构建一个检查单词中每个字符的查询,并确保该字符的出现次数不大于字符串中出现的次数? 或者这不是数据库的工作吗?

提前致谢。

1 个答案:

答案 0 :(得分:2)

这不是(关系型)数据库的工作,完全坦诚。

由于英语中的几千个单词,即使你把它们吹到所有可以想象的倾向,也不会超过粗略的10万字,我真的不明白你为什么要使用数据库。只需在python中编写一个内存中的单词列表,您就可以直接进行线性处理。

有几种方法可以更快地搜索大量数据,但关系数据库不能应用任何数据。此外,考虑到字母是单字节数据,速度增益应该可以忽略不计。

如果你担心性能:是的,在python中执行此操作确实会产生很大的运行时开销,因为计数字母非常快且可以高度优化,但python本身是一种复杂的语言并且执行它会设置一些限制。

考虑到要处理的数据量相当小,我的方法是:

  1. 准备一个词表:按字母顺序对词典中每个单词的字母进行排序,并使用排序后的字符串作为实际单词的键。你会发现一个排序的字符串可以映射到多个单词。
  2. 对手的字母进行排序
  3. 对于单词列表中的每个键,检查它是否是您手中的一部分。这应该非常快,因为之前的排序可以避免冗余检查(例如,如果您在单词列表的开头,第一个单词以a开头,但您的最低标记是e ,跳到以e开头的第一个单词。
  4. 任何类型的树结构在算法上都可以更快,但在大多数PC式处理器上,编写良好的C代码将编译为非常快速的SIMD字符串比较。