在文本中查找对称单词

时间:2013-04-19 04:10:35

标签: python function

我必须编写一个函数,它接受一个包含str形式的文本块的参数文本,并返回一个“对称”单词的排序列表。对称字被定义为一个单词,其中对于所有值i,字母i从单词的开头起定位,而字母i从单词的末尾起的位置与字母表的各个末端等距。例如,bevy是一个对称词,因为:b(从单词的开头开始的1个位置)是字母表的第二个字母,y(从单词的结尾开始的1个位置)是字母表的倒数第二个字母;和e(从单词的开头起2个位置)是字母表的第五个字母,v(单词末尾的2个位置)是字母表中倒数第5个字母。

例如:

>>> symmetrics("boy bread aloz bray")
['aloz','boy']
>>> symmetrics("There is a car and a book;")
['a']

所有我能想到的解决方案就是这个,但我不能运行它,因为它错了:

def symmetrics(text):
    func_char= ",.?!:'\/"
    for letter in text:
        if letter in func_char:
          text = text.replace(letter, ' ') 
    alpha1 = 'abcdefghijklmnopqrstuvwxyz'
    alpha2 = 'zyxwvutsrqponmlkjihgfedcba'
    sym = []
    for word in text.lower().split():
        n = range(0,len(word))
        if word[n] == word[len(word)-1-n]:
            sym.append(word)
        return sym

上面的代码没有考虑alpha1和alpha2的位置,因为我不知道如何把它。有没有人可以帮助我?

4 个答案:

答案 0 :(得分:3)

这是一个提示:

In [16]: alpha1.index('b')
Out[16]: 1

In [17]: alpha2.index('y')
Out[17]: 1

解决问题的另一种方法是使用str.translate()方法:

import string

def is_sym(word):
    alpha1 = 'abcdefghijklmnopqrstuvwxyz'
    alpha2 = 'zyxwvutsrqponmlkjihgfedcba'
    tr = string.maketrans(alpha1, alpha2)
    n = len(word) // 2
    return word[:n] == word[::-1][:n].translate(tr)

print(is_sym('aloz'))
print(is_sym('boy'))
print(is_sym('bread'))

(翻译表的构建可以很容易地计算出来。)

答案 1 :(得分:1)

for循环可以修改为:

for word in text.lower().split():
    for n in range(0,len(word)//2):
        if alpha1.index(word[n]) != alpha2.index(word[len(word)-1-n]):
            break
    else:
        sym.append(word)
return sym

答案 2 :(得分:0)

根据您的对称规则,我们可以使用以下is_symmetric_word函数验证对称字:

def is_symmetric_word(word):
    alpha1 = 'abcdefghijklmnopqrstuvwxyz'
    alpha2 = 'zyxwvutsrqponmlkjihgfedcba'
    length = len(word)
    for i in range(length / 2):
        if alpha1.index(word[i]) != alpha2.index(word[length - 1 - i]):
            return False

    return True

然后,从文本中获取所有唯一对称词的整个函数可以定义为:

def is_symmetrics(text):
    func_char= ",.?!:'\/;"
    for letter in text:
        if letter in func_char:
          text = text.replace(letter, ' ') 
    sym = []
    for word in text.lower().split():
        if is_symmetric_word(word) and not (word in sym):
            sym.append(word)

    return sym

以下是您的两个测试案例:

is_symmetrics("boy bread aloz bray")           #['boy', 'aloz']
is_symmetrics("There is a car and a book;")    #['a']

答案 3 :(得分:0)

代码优先。在代码下面讨论。

import string

# get alphabet and reversed alphabet
try:
    # Python 2.x
    alpha1 = string.lowercase
except AttributeError:
    # Python 3.x and newer
    alpha1 = string.ascii_lowercase

alpha2 = alpha1[::-1]  # use slicing to reverse alpha1

# make a dictionary where the key, value pairs are symmetric
# for example symd['a'] == 'z', symd['b'] == 'y', and so on
_symd = dict(zip(alpha1, alpha2))

def is_symmetric_word(word):
    if not word:
        return False  # zero-length word is not symmetric
    i1 = 0
    i2 = len(word) - 1
    while True:
        if i1 >= i2:
            return True  # we have checked the whole string
        # get a pair of chars
        c1 = word[i1]
        c2 = word[i2]
        if _symd[c1] != c2:
            return False # the pair wasn't symmetric
        i1 += 1
        i2 -= 1

# note, added a space to list of chars to filter to a space
_filter_to_space = ",.?!:'\/ "
def _filter_ch(ch):
    if ch in _filter_to_space:
        return ' '  # return a space 
    elif ch in alpha1:
        return ch # it's an alphabet letter so return it
    else:
        # It's something we don't want.  Return empty string.
        return ''

def clean(text):
    return ''.join(_filter_ch(ch) for ch in text.lower())

def symmetrics(text):
    # filter text: keep only chars in the alphabet or spaces
    for word in clean(text).split():
        if is_symmetric_word(word):
            # use of yield makes this a generator.
            yield word

lst = list(symmetrics("The boy...is a yob."))
print(lst)  # prints: ['boy', 'a', 'yob']
  • 无需输入两次字母;我们可以扭转第一个。

  • 我们可以制作一个字典,将每个字母与其对称字母配对。这将使得测试任何给定字母对是否是对称对非常容易。函数zip()由两个序列组成;它们需要长度相同,但由于我们使用字符串和字符串的反向副本,因此它们的长度相同。

  • 最好写一个简单的函数做一件事,所以我们写一个函数除了检查一个字符串是否对称外什么都不做。如果给它一个零长度字符串,则返回False,否则它将i1设置为字符串中的第一个字符,将i2设置为最后一个字符。它会对字符进行比较,只要它们继续对称,并在递减i1时递增i2。如果两者相遇或相互通过,我们知道我们已经看到整个字符串并且它必须是对称的,在这种情况下我们返回True;如果它找到任何不对称的字符对,则返回False。我们必须检查i1i2是否在循环的顶部遇到或传递,因此它不会尝试检查字符是否是它自己的对称字符。 (一个字符不能同时是'a''z',所以字符永远不是它自己的对称字符!)

  • 现在我们编写一个过滤掉垃圾的包装器,将字符串拆分成单词,然后测试每个单词。它不仅将选定的标点字符转换为空格,而且还删除任何意外字符(任何不是批准的标点字符,空格或字母)。这样我们就知道任何意想不到的东西都会通过内部功能。包装器是“懒惰的”......它是一个一次生成一个单词的生成器,而不是构建整个列表并返回它。使用list()可以很容易地将生成器的结果强制转换为列表。如果需要,您可以轻松修改此功能,只需构建一个列表并将其返回。

如果您对此有任何疑问,请询问。

编辑:代码的原始版本没有用标点字符做正确的事情;这个版本呢。另外,正如@heltonbiker建议的那样,为什么在Python有你可以使用的副本时输入字母?所以我也做了那个改变。

编辑:@heltonbiker的更改引入了对Python版本的依赖!我使用合适的try: / except块将其留下来处理问题。似乎Python 3.x已将小写ASCII字母的名称改为string.ascii_lowercase而不是普通string.lowercase

相关问题