أفضل طريقة لإزالة علامات الترقيم من السلسلة

StackOverflow https://stackoverflow.com/questions/265960

  •  06-07-2019
  •  | 
  •  

سؤال

يبدو أنه يجب أن تكون هناك طريقة أبسط من:

import string
s = "string. With. Punctuation?" # Sample string 
out = s.translate(string.maketrans("",""), string.punctuation)

هل هناك؟

هل كانت مفيدة؟

المحلول

ومن منظور الكفاءة، وأنت لن تغلب

s.translate(None, string.punctuation)

لإصدارات أعلى من بيثون استخدام التعليمات البرمجية التالية:

s.translate(str.maketrans('', '', string.punctuation))

وانها تنفيذ عمليات سلسلة الخام في C مع جدول بحث - ليس هناك الكثير من شأنها أن تغلب ولكن كتابة التعليمات البرمجية C الخاصة بك

إذا السرعة ليست مصدر قلق، هناك خيار آخر هو على الرغم من:

exclude = set(string.punctuation)
s = ''.join(ch for ch in s if ch not in exclude)

وهذا هو أسرع من s.replace مع كل حرف، ولكن لن تؤدي كذلك النهج الثعبان غير نقية مثل regexes أو string.translate، وكما ترون من توقيت أدناه. لهذا النوع من المشكلة، يفعلون ذلك في أدنى مستوى مستوى ممكن يؤتي ثماره.

وكود التوقيت:

import re, string, timeit

s = "string. With. Punctuation"
exclude = set(string.punctuation)
table = string.maketrans("","")
regex = re.compile('[%s]' % re.escape(string.punctuation))

def test_set(s):
    return ''.join(ch for ch in s if ch not in exclude)

def test_re(s):  # From Vinko's solution, with fix.
    return regex.sub('', s)

def test_trans(s):
    return s.translate(table, string.punctuation)

def test_repl(s):  # From S.Lott's solution
    for c in string.punctuation:
        s=s.replace(c,"")
    return s

print "sets      :",timeit.Timer('f(s)', 'from __main__ import s,test_set as f').timeit(1000000)
print "regex     :",timeit.Timer('f(s)', 'from __main__ import s,test_re as f').timeit(1000000)
print "translate :",timeit.Timer('f(s)', 'from __main__ import s,test_trans as f').timeit(1000000)
print "replace   :",timeit.Timer('f(s)', 'from __main__ import s,test_repl as f').timeit(1000000)

وهذا يعطي النتائج التالية:

sets      : 19.8566138744
regex     : 6.86155414581
translate : 2.12455511093
replace   : 28.4436721802

نصائح أخرى

والتعبيرات العادية هي بسيطة بما فيه الكفاية، إذا كنت تعرف لهم.

import re
s = "string. With. Punctuation?"
s = re.sub(r'[^\w\s]','',s)

في رمز أعلاه، فإننا استبدال (re.sub) ممنوع [أحرف أبجدية رقمية (\ ث) والمساحات (\ ق)] مع سلسلة فارغة.
بالتالي . و؟ وعلامات الترقيم لا تكون موجودة في المتغير الصورة "بعد تشغيل الصورة المتغير من خلال التعابير المنطقية.

لتسهيل الاستخدام، قمت بتلخيص ملاحظة شريطية علامات الترقيم من سلسلة في كل من Python 2 وPython 3.يرجى الرجوع إلى الإجابات الأخرى للحصول على الوصف التفصيلي.


بايثون 2

import string

s = "string. With. Punctuation?"
table = string.maketrans("","")
new_s = s.translate(table, string.punctuation)      # Output: string without punctuation

بايثون 3

import string

s = "string. With. Punctuation?"
table = str.maketrans({key: None for key in string.punctuation})
new_s = s.translate(table)                          # Output: string without punctuation
myString.translate(None, string.punctuation)

وعادة ما تستخدم شيئا من هذا القبيل:

>>> s = "string. With. Punctuation?" # Sample string
>>> import string
>>> for c in string.punctuation:
...     s= s.replace(c,"")
...
>>> s
'string With Punctuation'

وstring.punctuation غير ASCII <م> فقط ! وهناك طريقة أكثر الصحيحة (ولكن أيضا أبطأ بكثير) هو استخدام وحدة unicodedata:

# -*- coding: utf-8 -*-
from unicodedata import category
s = u'String — with -  «punctation »...'
s = ''.join(ch for ch in s if category(ch)[0] != 'P')
print 'stripped', s

وليس بالضرورة أكثر بساطة، ولكن بطريقة مختلفة، إذا كنت أكثر دراية عائلة إعادة.

import re, string
s = "string. With. Punctuation?" # Sample string 
out = re.sub('[%s]' % re.escape(string.punctuation), '', s)

لبيثون 3 str أو بايثون 2 القيم unicode، str.translate() يستغرق سوى القاموس. وبدا codepoints (أعداد صحيحة) حتى في ذلك رسم الخرائط وأي شيء معين لإزالة None.

لإزالة (بعض؟) علامات الترقيم ثم، الاستخدام:

import string

remove_punct_map = dict.fromkeys(map(ord, string.punctuation))
s.translate(remove_punct_map)

dict.fromkeys() أسلوب فئة يجعل من تافهة لإنشاء رسم الخرائط، ووضع جميع القيم إلى None على أساس تسلسل مفاتيح.

لإزالة <م> جميع علامات الترقيم، وليس فقط ASCII علامات الترقيم، يحتاج الجدول الخاص بك أن تكون أكبر قليلا، يمكنك الاطلاع على J.F. سيباستيان الجواب (بيثون 3 الإصدار):

import unicodedata
import sys

remove_punct_map = dict.fromkeys(i for i in range(sys.maxunicode)
                                 if unicodedata.category(chr(i)).startswith('P'))

string.punctuation يفتقد الكثير من علامات الترقيم التي يشيع استخدامها في العالم الحقيقي.ماذا عن الحل الذي يعمل مع علامات الترقيم غير ASCII؟

import regex
s = u"string. With. Some・Really Weird、Non?ASCII。 「(Punctuation)」?"
remove = regex.compile(ur'[\p{C}|\p{M}|\p{P}|\p{S}|\p{Z}]+', regex.UNICODE)
remove.sub(u" ", s).strip()

أنا شخصياً أعتقد أن هذه هي أفضل طريقة لإزالة علامات الترقيم من سلسلة في بايثون للأسباب التالية:

  • فهو يزيل كافة علامات الترقيم Unicode
  • إنه قابل للتعديل بسهولة، على سبيل المثال.يمكنك إزالة \{S} إذا كنت تريد إزالة علامات الترقيم، مع الاحتفاظ بالرموز مثل $.
  • يمكنك أن تكون محددًا بشأن ما تريد الاحتفاظ به وما تريد إزالته، على سبيل المثال \{Pd} سوف يزيل الشرطات فقط.
  • يعمل هذا التعبير العادي أيضًا على تطبيع المسافة البيضاء.يقوم بتعيين علامات التبويب وأحرف الإرجاع والأشياء الغريبة الأخرى إلى مسافات فردية لطيفة.

يستخدم هذا خصائص أحرف Unicode، والتي يمكنك قراءة المزيد عنه على ويكيبيديا.

وهذا قد لا يكون أفضل حل ولكن هذا هو كيف فعلت ذلك.

import string
f = lambda x: ''.join([i for i in x if i not in string.punctuation])

وهنا هي وظيفة كتبت. انها ليست فعالة جدا، ولكنها بسيطة ويمكنك إضافة أو إزالة أي علامات الترقيم التي تريدها:

def stripPunc(wordList):
    """Strips punctuation from list of words"""
    puncList = [".",";",":","!","?","/","\\",",","#","@","$","&",")","(","\""]
    for punc in puncList:
        for word in wordList:
            wordList=[word.replace(punc,'') for word in wordList]
    return wordList

وفيما يلي الخطوط الملاحية المنتظمة واحدة لبيثون 3.5:

import string
"l*ots! o(f. p@u)n[c}t]u[a'ti\"on#$^?/".translate(str.maketrans({a:None for a in string.punctuation}))

وأنا لم أر هذه الإجابة حتى الان. مجرد استخدام التعابير المنطقية. يزيل كل الحروف إلى جانب شخصيات كلمة (\w) والحروف عدد (\d)، متبوعا حرف مسافة بيضاء (\s):

import re
s = "string. With. Punctuation?" # Sample string 
out = re.sub(ur'[^\w\d\s]+', '', s)

إليك الحل بدون regex.

import string

input_text = "!where??and!!or$$then:)"
punctuation_replacer = string.maketrans(string.punctuation, ' '*len(string.punctuation))    
print ' '.join(input_text.translate(punctuation_replacer).split()).strip()

Output>> where and or then
  • يستبدل علامات الترقيم بمسافات
  • استبدال المسافات المتعددة بين الكلمات بمسافة واحدة
  • قم بإزالة المساحات الزائدة ، إن وجدت مع الشريط ()

وكما تحديثا، وأعاد كتابة سبيل المثالBrian في بيثون 3 وإجراء تغييرات على أن تتحرك خطوة التعابير المنطقية الترجمة داخل الدالة. هنا كان لي التفكير في الوقت المحدد في كل خطوة واحدة اللازمة لجعل عمل الوظيفة. ربما كنت تستخدم الحوسبة الموزعة ولا يمكن أن يكون الكائن رجإكس تقاسمها بين العاملين لديك وتحتاج إلى أن يكون خطوة re.compile في كل عامل. أيضا، كان من الغريب أن اثنين من مرة وتطبيقات مختلفة من maketrans لبيثون 3

table = str.maketrans({key: None for key in string.punctuation})

ومقابل

table = str.maketrans('', '', string.punctuation)

بالاضافة الى أضفت طريقة أخرى لاستخدام مجموعة، حيث أستفيد من وظيفة تقاطع للحد من عدد التكرارات.

وهذا هو رمز الكامل:

import re, string, timeit

s = "string. With. Punctuation"


def test_set(s):
    exclude = set(string.punctuation)
    return ''.join(ch for ch in s if ch not in exclude)


def test_set2(s):
    _punctuation = set(string.punctuation)
    for punct in set(s).intersection(_punctuation):
        s = s.replace(punct, ' ')
    return ' '.join(s.split())


def test_re(s):  # From Vinko's solution, with fix.
    regex = re.compile('[%s]' % re.escape(string.punctuation))
    return regex.sub('', s)


def test_trans(s):
    table = str.maketrans({key: None for key in string.punctuation})
    return s.translate(table)


def test_trans2(s):
    table = str.maketrans('', '', string.punctuation)
    return(s.translate(table))


def test_repl(s):  # From S.Lott's solution
    for c in string.punctuation:
        s=s.replace(c,"")
    return s


print("sets      :",timeit.Timer('f(s)', 'from __main__ import s,test_set as f').timeit(1000000))
print("sets2      :",timeit.Timer('f(s)', 'from __main__ import s,test_set2 as f').timeit(1000000))
print("regex     :",timeit.Timer('f(s)', 'from __main__ import s,test_re as f').timeit(1000000))
print("translate :",timeit.Timer('f(s)', 'from __main__ import s,test_trans as f').timeit(1000000))
print("translate2 :",timeit.Timer('f(s)', 'from __main__ import s,test_trans2 as f').timeit(1000000))
print("replace   :",timeit.Timer('f(s)', 'from __main__ import s,test_repl as f').timeit(1000000))

وهذا هو بلدي النتائج:

sets      : 3.1830138750374317
sets2      : 2.189873124472797
regex     : 7.142953420989215
translate : 4.243278483860195
translate2 : 2.427158243022859
replace   : 4.579746678471565
>>> s = "string. With. Punctuation?"
>>> s = re.sub(r'[^\w\s]','',s)
>>> re.split(r'\s*', s)


['string', 'With', 'Punctuation']
import re
s = "string. With. Punctuation?" # Sample string 
out = re.sub(r'[^a-zA-Z0-9\s]', '', s)

وA-بطانة واحدة قد تكون مفيدة في الحالات التي لم صارمة جدا:

''.join([c for c in s if c.isalnum() or c.isspace()])
#FIRST METHOD
#Storing all punctuations in a variable    
punctuation='!?,.:;"\')(_-'
newstring='' #Creating empty string
word=raw_input("Enter string: ")
for i in word:
     if(i not in punctuation):
                  newstring+=i
print "The string without punctuation is",newstring

#SECOND METHOD
word=raw_input("Enter string: ")
punctuation='!?,.:;"\')(_-'
newstring=word.translate(None,punctuation)
print "The string without punctuation is",newstring


#Output for both methods
Enter string: hello! welcome -to_python(programming.language)??,
The string without punctuation is: hello welcome topythonprogramminglanguage
with open('one.txt','r')as myFile:

    str1=myFile.read()

    print(str1)


    punctuation = ['(', ')', '?', ':', ';', ',', '.', '!', '/', '"', "'"] 

for i in punctuation:

        str1 = str1.replace(i," ") 
        myList=[]
        myList.extend(str1.split(" "))
print (str1) 
for i in myList:

    print(i,end='\n')
    print ("____________")

وإزالة كلمات التوقف من ملف نصي باستخدام بايثون

print('====THIS IS HOW TO REMOVE STOP WORS====')

with open('one.txt','r')as myFile:

    str1=myFile.read()

    stop_words ="not", "is", "it", "By","between","This","By","A","when","And","up","Then","was","by","It","If","can","an","he","This","or","And","a","i","it","am","at","on","in","of","to","is","so","too","my","the","and","but","are","very","here","even","from","them","then","than","this","that","though","be","But","these"

    myList=[]

    myList.extend(str1.split(" "))

    for i in myList:

        if i not in stop_words:

            print ("____________")

            print(i,end='\n')

وهذه هي الطريقة لتغيير وثائقنا إلى أحرف كبيرة أو أقل القضية.

print('@@@@This is lower case@@@@')

with open('students.txt','r')as myFile:

    str1=myFile.read()
    str1.lower()
print(str1.lower())

print('*****This is upper case****')

with open('students.txt','r')as myFile:

    str1=myFile.read()

    str1.upper()

print(str1.upper())

وأود أن استخدام وظيفة من هذا القبيل:

def scrub(abc):
    while abc[-1] is in list(string.punctuation):
        abc=abc[:-1]
    while abc[0] is in list(string.punctuation):
        abc=abc[1:]
    return abc
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top