【问题标题】:Python String Comparisons Using A Word List使用单词列表的 Python 字符串比较
【发布时间】:2013-03-29 22:23:22
【问题描述】:

最终我将能够在聊天室中发布类似这样的简单问题,但现在我必须发布它。我仍在努力解决 Python 中的比较问题。我有一个包含从文件中获得的字符串的列表。我有一个函数,它接收单词列表(以前从文件创建)和一些“密文”。我正在尝试使用 Shift Cipher 蛮力破解密文。我的问题与比较整数相同。虽然我在尝试使用打印语句进行调试时可以看到,我的密文将被转移到单词列表中的一个单词,但它永远不会评估为 True。我可能正在比较两种不同的变量类型,或者 /n 可能会导致比较失败。对不起今天的所有帖子,我今天正在做很多练习题,为即将到来的作业做准备。

  def shift_encrypt(s, m):

   shiftAmt = s % 26
   msgAsNumList = string2nlist(m)

   shiftedNumList = add_val_mod26(msgAsNumList, shiftAmt)
   print 'Here is the shifted number list: ', shiftedNumList

   # Take the shifted number list and convert it back to a string
   numListtoMsg = nlist2string(shiftedNumList)
   msgString = ''.join(numListtoMsg)

   return msgString

 def add_val_mod26(nlist, value):
   newValue = value % 26
   print 'Value to Add after mod 26: ', newValue
   listLen = len(nlist)
   index = 0
   while index < listLen:
       nlist[index] = (nlist[index] + newValue) % 26
       index = index + 1
   return nlist

 def string2nlist(m):
   characters =    ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
   numbers = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]
   newList = []
   msgLen = len(m)         # var msgLen will be an integer of the length

   index = 0               # iterate through message length in while loop
   while index < msgLen:
       letter = m[index]   # iterate through message m
       i = 0
       while i < 26:
           if letter == characters[i]:
               newList.append(numbers[i])
           i = i + 1
       index = index + 1
    return newList

  def nlist2string(nlist):
    characters = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
    numbers = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]
    newList = []
    nListLen = len(nlist)

    index = 0
    while index < nListLen:
        num = nlist[index]
        newNum = num % 26
        i = 0
        while i < 26:
            num1 = newNum
            num2 = numbers[i]
            if (num1 == num2):
            newList.append(characters[i])
        i = i + 1
    index = index + 1
    return newList


  def wordList(filename):

    fileObject = open(filename, "r+")                    
    wordsList = fileObject.readlines()
    return wordsList


  def shift_computePlaintext(wlist, c):

    index = 0
    while index < 26:
        newCipher = shift_encrypt(index, c)
        print 'The new cipher text is: ', newCipher
        wordlistLen = len(wlist)
        i = 0
        while i < wordlistLen:
            print wlist[i]
            if newCipher == wlist[i]:
                return newCipher
            else:
                print 'Word not found.'
            i = i + 1
        index = index + 1    

   print 'Take Ciphertext and Find Plaintext from Wordlist Function: \n'
   list = wordList('test.txt')
   print list
   plainText = shift_computePlaintext(list, 'vium')
   print 'The plaintext was found in the wordlist: ', plainText

当移位量 = 18 时,密文 = 名称,这是我的单词列表中的一个单词,但它永远不会评估为 True。提前感谢您的帮助!

【问题讨论】:

  • 尝试打印repr(x) 而不是x。这将使您更容易看到额外的'\n' 或其他空白字符,以及区分'2'2,以及您正在谈论的所有其他内容。
  • 同时,您能否给我们test.txt 的内容,并修复缩进,并包含一个完整的示例(所有这些函数shift_encrypt 调用),这样我们就可以实际运行您的代码并进行调试是吗?
  • 附带说明,调用变量list 是个坏主意,因为这是内置list 类型的名称,您将无法再访问它。
  • 对不起!好的,所以 test.txt 每行包含一个单词: 你好,我的名字是 jesi 这就是它的全部内容,因为我只是在测试它。我将编辑以上内容以添加其他功能。
  • @abarnert 好的,所以我添加了我认为运行/调试所需的所有内容。我将变量名称列表更改为其他名称,感谢您的帮助!

标签: python list string-comparison


【解决方案1】:

我们目前掌握的信息很难确定,但这里有一个猜测:

wordsList = fileObject.readlines()

这将返回一个 list 的字符串并保留换行符,例如:

['hello\n', 'my\n', 'name\n', 'is\n', 'jesi\n']

因此,在shift_computePlaintext 内部,当您遍历wlist 寻找与解密的'vium' 匹配的内容时,您正在寻找与'name' 匹配的字符串,但它们都不匹配,包括@987654329 @。

换句话说,正是你所怀疑的。

有几种方法可以解决这个问题,但最明显的是使用wlist[i].strip() 而不是wlist[i],或者首先使用类似wordsList = [line.strip() for line in fileObject] 而不是wordsList = fileObject.readlines() 来剥离所有内容。


一些旁注:

打电话给readlines() 几乎没有充分的理由。这会返回一个您可以迭代的行列表……但文件对象本身已经是一个可以迭代的行的迭代。如果您确实需要确保它是一个列表而不是其他类型的可迭代对象,或者制作一个单独的副本以供以后使用,或者其他什么,只需在其上调用 list,就像处理任何其他可迭代对象一样。

你几乎不应该写这样的循环:

index = 0
while index < 26:
    # ...
    index = index + 1

相反,只需这样做:

for index in range(26):

它更容易阅读,更难出错(微妙的逐个错误是你一生中令人沮丧的调试一半的原因)等等。

如果你在一个集合的长度上循环,甚至不要这样做。而不是这个:

wordlistLen = len(wlist)
i = 0
while i < wordlistLen:
    # ...
    word = wlist[i]
    # ...
    i = i + 1

……就这样做吧:

for word in wlist:

……或者,如果您同时需要 iword(您偶尔会这样做):

for i, word in enumerate(wlist):

同时,如果您循环一个集合的唯一原因是检查它的每个值,那么您甚至不需要这样做。而不是这个:

wordlistLen = len(wlist)
while i < wordlistLen:
    print wlist[i]
    if newCipher == wlist[i]:
        return newCipher
    else:
        print 'Word not found.'
    i = i + 1

……就这样做吧:

if newCipher in wlist:
    return newCipher
else:
    print 'Word not found.'

在这里,您实际上遇到了其中一个微妙的错误:您一遍又一遍地打印“Word not found”,而不是在未找到时仅在最后打印一次。

【讨论】:

  • @DSM 我同意!类似结构的答案可以在Code Review找到。
  • 我感觉就是这样。谢谢您的帮助!我使用 wlist[i].strip() 它能够找到匹配的单词。谢谢一百万!
  • @abarnert:我很高兴我知道问题出在哪里,但我不知道如何摆脱 \n 的问题。再次感谢。
  • @jesiKat:没问题。一旦你看过strip,即使你不记得具体是怎么做的,你应该能够通过文档或内置帮助或谷歌搜索找到它……但如果你以前从未见过它,你甚至不知道要寻找什么。
  • @abarnet 帮助很大,谢谢!!我正在观看教程视频并在网上关注其他一些视频,所以我基本上只是按照他们现在告诉我的去做。我确信到本季度末我的代码会更有效率,但目前,我只是想让它在没有错误的情况下运行。但我绝对感谢您的帮助,我一定会采纳的!
猜你喜欢
  • 1970-01-01
  • 2012-11-07
  • 2015-11-21
  • 2021-05-09
  • 2016-06-10
  • 2019-04-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多