【问题标题】:How can i strip punctuation from a string and then add it back at the same index later?如何从字符串中删除标点符号,然后稍后将其添加回同一索引?
【发布时间】:2013-02-27 06:52:04
【问题描述】:

我希望程序假设我的 word_str 是“例如,这是‘剑桥大学’”。如果单词的长度大于 3 个字符,它将保留单词的第一个和最后一个字母,并打乱单词的内部。我的问题是它错误地在单词的开头或结尾用标点符号打乱了单词。我需要它来洗牌,以便标点符号保留在正确的索引中,然后保留单词的第一个和最后一个字母,并在单词的内部洗牌,如果有的话,在末尾添加标点符号。有什么想法吗?

def scramble_word(word_str):
char = ".,!?';:"
import random
if len(word_str) <= 3:
    return word_str + ' '
else:
    word_str = word_str.strip(char)
    word_str = list(word_str)
    scramble = word_str[1:-1]
    random.shuffle(scramble)
    scramble = ''.join(scramble)
    word_str = ''.join(word_str)
    new_word = word_str[0] + scramble + word_str[-1]
    return new_word + ' '

【问题讨论】:

  • 为什么不只打乱字母而忽略标点符号?
  • 因为程序规范要求我不要忽略标点符号
  • 但是如果你将它放回 在同一个地方就像在打乱之前一样,这在本质上完全模仿了忽略它的结果,同时打乱了字母数字字符.还是我错过了什么?
  • 我怎么能打乱和忽略标点符号而只打乱字母数字?

标签: python string list function punctuation


【解决方案1】:

使用正则表达式:

import random
import re

random.seed(1234) #remove this in production, just for replication of my results

def shuffle_word(m):
    word = m.group()
    inner = ''.join(random.sample(word[1:-1], len(word) - 2))
    return '%s%s%s' % (word[0], inner, word[-1])
    
s = """This is 'Cambridge University' for example."""

print re.sub(r'\b\w{3}\w+\b', shuffle_word, s)

打印出来的

Tihs is 'Cadibrgme Uinrtvsiey' for exlampe.

re.sub 允许您向它传递一个函数(它接受一个正则表达式匹配对象)而不是替换字符串。

编辑 - 没有正则表达式

from StringIO import StringIO

def shuffle_word(m):
    inner = ''.join(random.sample(m[1:-1], len(m) - 2))
    return '%s%s%s' % (m[0], inner, m[-1])

def scramble(text)
    sio = StringIO(text)
    accum = []
    start = None
    while sio.tell() < sio.len:
        char = sio.read(1)
        if start is None:
            if char.isalnum():
                start = sio.tell() - 1
            else:
                accum.append(char)
        elif not char.isalnum():
            end = sio.tell() - 1
            sio.seek(start)
            accum.append(shuffle_word(sio.read(end - start)))
            print accum[-1]
            start = None
    else:
        if start is not None:
            sio.seek(start)
            word = sio.read()
            if len(word) > 3:
                accum.append(shuffle_word(sio.read()))
            else:
                accum.append(word)
    
    return ''.join(accum)

s = """This is 'Cambridge University' for example."""
print scramble(s)

【讨论】:

  • 一个不错的解决方案。本来建议使用 re.split() 拆分文本并在通过 scramble_word 传递单词后重新组装它,但将函数传递给 re.sub 更加优雅。
  • 没有 re.sub 怎么办?
  • @MikePang:你的意思是没有re.sub,还是一般没有正则表达式?
  • 没有正则表达式!
  • 我会更新我的问题来解决这个问题,但你到底为什么要这样做?
【解决方案2】:

使用正则表达式非常简单:

import re
import random

s = ('Pitcairn Islands, Saint Helena, '
     'Ascension and Tristan da Cunha, '
     'Saint Kitts and Nevis, '
     'Saint Vincent and the Grenadines, Singapore')

reg = re.compile('(?<=[a-zA-Z])[a-zA-Z]{2,}(?=[a-zA-Z])')

def ripl(m):
    g = list(m.group())
    random.shuffle(g)
    return ''.join(g)

print reg.sub(ripl,s)

结果

Piictran Islands, Sanit Heelna, Asnioecsn and Tiastrn da Cunha, Sniat Ktits and Neivs, Snait Vnnceit and the Giearndens, Snoiaprge

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多