अजगर में सबसे कारगर तरीका सभी लोअरकेस सभी गैर-ascii अल्फा वर्ण बाहर अलग करना के लिए एक स्ट्रिंग परिवर्तित करने के लिए क्या है?

वोट
27

मैं एक साधारण कार्य मैं अजगर है, जो सभी लोअरकेस के लिए एक स्ट्रिंग को बदलने और सभी गैर-ascii गैर अल्फा वर्ण बाहर पट्टी में प्रदर्शन करने की जरूरत है।

उदाहरण के लिए:

This is a Test -> thisisatest
A235th@#$&( er Ra{}|?>ndom -> atherrandom

मैं यह करने के लिए एक सरल कार्य है:

import string
import sys

def strip_string_to_lowercase(s):
    tmpStr = s.lower().strip()
    retStrList = []
    for x in tmpStr:
        if x in string.ascii_lowercase:
            retStrList.append(x)

    return ''.join(retStrList)

लेकिन मैं सोच नहीं मदद कर सकते है एक अधिक कुशल, या और अधिक सुरुचिपूर्ण, जिस तरह से।

धन्यवाद!


संपादित करें:

सभी उन है कि जवाब के लिए धन्यवाद। मुझे पता चला, और कुछ मामलों में फिर से सीखा है, अजगर का एक अच्छा सौदा।

12/03/2009 को 15:35
का स्रोत उपयोगकर्ता
अन्य भाषाओं में...                            


11 जवाब

वोट
24

हालांकि ध्यान दें कि यह यूनिकोड के लिए काम नहीं करेगा - एक अन्य समाधान (कि pythonic नहीं है, लेकिन बहुत तेजी से) string.translate उपयोग करने के लिए है। ऐसा नहीं है कि आप में तेजी लाने के कर सकते हैं भी ध्यान देने योग्य है दाना के कोड एक सेट (जो हैश द्वारा लग रहा है, बल्कि एक रेखीय खोज हर बार प्रदर्शन की तुलना में) में पात्रों को ले जाकर। यहाँ समय मैं दिया समाधान के विभिन्न के लिए प्राप्त कर रहे हैं:

import string, re, timeit

# Precomputed values (for str_join_set and translate)

letter_set = frozenset(string.ascii_lowercase + string.ascii_uppercase)
tab = string.maketrans(string.ascii_lowercase + string.ascii_uppercase,
                       string.ascii_lowercase * 2)
deletions = ''.join(ch for ch in map(chr,range(256)) if ch not in letter_set)

s="A235th@#$&( er Ra{}|?>ndom"

# From unwind's filter approach
def test_filter(s):
    return filter(lambda x: x in string.ascii_lowercase, s.lower())

# using set instead (and contains)
def test_filter_set(s):
    return filter(letter_set.__contains__, s).lower()

# Tomalak's solution
def test_regex(s):
    return re.sub('[^a-z]', '', s.lower())

# Dana's
def test_str_join(s):
    return ''.join(c for c in s.lower() if c in string.ascii_lowercase)

# Modified to use a set.
def test_str_join_set(s):
    return ''.join(c for c in s.lower() if c in letter_set)

# Translate approach.
def test_translate(s):
    return string.translate(s, tab, deletions)


for test in sorted(globals()):
    if test.startswith("test_"):
        assert globals()[test](s)=='atherrandom'
        print "%30s : %s" % (test, timeit.Timer("f(s)", 
              "from __main__ import %s as f, s" % test).timeit(200000))

यह मैं देता है:

               test_filter : 2.57138351271
           test_filter_set : 0.981806765698
                test_regex : 3.10069885233
             test_str_join : 2.87172979743
         test_str_join_set : 2.43197956381
            test_translate : 0.335367566218

[संपादित करें] साथ ही फिल्टर समाधान के साथ अपडेट किया गया। (ध्यान दें कि का उपयोग कर set.__contains__एक बड़ा अंतर यहाँ बना देता है, के रूप में यह लैम्ब्डा के लिए एक अतिरिक्त समारोह कॉल कर टाल।

12/03/2009 को 17:06
का स्रोत उपयोगकर्ता

वोट
17
>>> filter(str.isalpha, "This is a Test").lower()
'thisisatest'
>>> filter(str.isalpha, "A235th@#$&( er Ra{}|?>ndom").lower()
'atherrandom'
12/03/2009 को 16:55
का स्रोत उपयोगकर्ता

वोट
11

नहीं विशेष रूप से कुशल, लेकिन निश्चित रूप से गरीब, थक सांकेतिक शब्दों में बदलनेवाला आंखों पर अच्छे रनटाइम:

def strip_string_and_lowercase(s):
    return ''.join(c for c in s.lower() if c in string.ascii_lowercase)
12/03/2009 को 15:39
का स्रोत उपयोगकर्ता

वोट
8

मैं:

  • स्ट्रिंग लोअरकेस
  • सभी को बदलने के [^a-z]साथ""

उसके जैसा:

def strip_string_to_lowercase():
  nonascii = re.compile('[^a-z]')
  return lambda s: nonascii.sub('', s.lower().strip())

संपादित करें: ऐसा लगता है (नीचे) मूल संस्करण वास्तव में धीमी है कि, हालांकि कुछ प्रदर्शन यह एक बंद (ऊपर) में परिवर्तित करने के द्वारा प्राप्त किया जा सकता है।

def strip_string_to_lowercase(s):
  return re.sub('[^a-z]', '', s.lower().strip())

स्ट्रिंग के खिलाफ 100,000 पुनरावृत्तियों के साथ मेरा प्रदर्शन माप

"A235th@#$&( er Ra{}|?>ndom"

पता चला कि:

परीक्षण के लिए, मैंने नहीं किया printपरिणाम है।

12/03/2009 को 15:39
का स्रोत उपयोगकर्ता

वोट
6

अजगर 2.x translateविधि

लोअरकेस और गैर-ascii गैर अल्फा वर्ण फिल्टर करने के लिए कनवर्ट करें:

from string import ascii_letters, ascii_lowercase, maketrans

table = maketrans(ascii_letters, ascii_lowercase*2)
deletechars = ''.join(set(maketrans('','')) - set(ascii_letters))

print "A235th@#$&( er Ra{}|?>ndom".translate(table, deletechars)
# -> 'atherrandom'

अजगर 3 translateविधि

फ़िल्टर गैर- ASCII:

ascii_bytes = "A235th@#$&(٠٫٢٥ er Ra{}|?>ndom".encode('ascii', 'ignore')

का प्रयोग करें bytes.translate()लोअरकेस और गैर अल्फा बाइट्स नष्ट करने के लिए कन्वर्ट करने के लिए:

from string import ascii_letters, ascii_lowercase

alpha, lower = [s.encode('ascii') for s in [ascii_letters, ascii_lowercase]]
table = bytes.maketrans(alpha, lower*2)           # convert to lowercase
deletebytes = bytes(set(range(256)) - set(alpha)) # delete nonalpha

print(ascii_bytes.translate(table, deletebytes))
# -> b'atherrandom'
12/03/2009 को 18:56
का स्रोत उपयोगकर्ता

वोट
4

@ दाना के लिए इसी तरह की है, लेकिन मैं इस एक फ़िल्टर काम की तरह लगता है लगता है, और है कि कोड में दिखाई देना चाहिए। इसके अलावा जरूरत स्पष्ट रूप से कॉल करने के लिए बिना join():

def strip_string_to_lowercase(s):
  return filter(lambda x: x in string.ascii_lowercase, s.lower())
12/03/2009 को 15:44
का स्रोत उपयोगकर्ता

वोट
3

मैं ब्रायन के कोड में फिल्टर समाधान कहा:

import string, re, timeit

# Precomputed values (for str_join_set and translate)

letter_set = frozenset(string.ascii_lowercase + string.ascii_uppercase)
tab = string.maketrans(string.ascii_lowercase + string.ascii_uppercase,
                       string.ascii_lowercase * 2)
deletions = ''.join(ch for ch in map(chr,range(256)) if ch not in letter_set)

s="A235th@#$&( er Ra{}|?>ndom"

def test_original(s):
    tmpStr = s.lower().strip()
    retStrList = []
    for x in tmpStr:
        if x in string.ascii_lowercase:
            retStrList.append(x)

    return ''.join(retStrList)


def test_regex(s):
    return re.sub('[^a-z]', '', s.lower())

def test_regex_closure(s):
  nonascii = re.compile('[^a-z]')
  def replacer(s):
    return nonascii.sub('', s.lower().strip())
  return replacer(s)


def test_str_join(s):
    return ''.join(c for c in s.lower() if c in string.ascii_lowercase)

def test_str_join_set(s):
    return ''.join(c for c in s.lower() if c in letter_set)

def test_filter_set(s):
    return filter(letter_set.__contains__, s.lower())

def test_filter_isalpha(s):
    return filter(str.isalpha, s).lower()

def test_filter_lambda(s):
    return filter(lambda x: x in string.ascii_lowercase, s.lower())

def test_translate(s):
    return string.translate(s, tab, deletions)

for test in sorted(globals()):
    if test.startswith("test_"):
        print "%30s : %s" % (test, timeit.Timer("f(s)", 
              "from __main__ import %s as f, s" % test).timeit(200000))

यह मैं देता है:

       test_filter_isalpha : 1.31981746283
        test_filter_lambda : 2.23935583992
           test_filter_set : 0.76511679557
             test_original : 2.13079176264
                test_regex : 2.44295629752
        test_regex_closure : 2.65205913042
             test_str_join : 2.25571266739
         test_str_join_set : 1.75565888961
            test_translate : 0.269259640541

ऐसा लगता है कि isalpha एक ऐसी ही कलन विधि का उपयोग किया जाता है, कम से कम ओ () के मामले में, सेट एल्गोरिथ्म के लिए।


संपादित करें: फ़िल्टर सेट जोड़ा गया, और फिल्टर कार्यों का नाम बदला थोड़ा और स्पष्ट होना।

12/03/2009 को 17:20
का स्रोत उपयोगकर्ता

वोट
2

इस सूची में compehension का एक विशिष्ट अनुप्रयोग है:

import string
s = "O235th@#$&( er Ra{}|?<ndom"
print ''.join(c for c in s.lower() if c in string.ascii_lowercase)

यह पता फिल्टर करेगा नहीं "<" (html इकाई), अपने उदाहरण के रूप में है, लेकिन मुझे लगता है कि आकस्मिक कटौती और पिछले समस्या थी।

12/03/2009 को 15:43
का स्रोत उपयोगकर्ता

वोट
2
>>> import string
>>> a = "O235th@#$&( er Ra{}|?&lt;ndom"
>>> ''.join(i for i in a.lower() if i in string.ascii_lowercase)
'otheraltndom'

अनिवार्य रूप से आप के रूप में ही कर रही है।

12/03/2009 को 15:42
का स्रोत उपयोगकर्ता

वोट
0

अजगर 2.x:

import string
valid_chars= string.ascii_lowercase + string.ascii_uppercase

def only_lower_ascii_alpha(text):
    return filter(valid_chars.__contains__, text).lower()

या तो साथ काम करता है strया unicodeतर्क।

>>> only_lower_ascii_alpha("Hello there 123456!")
'hellothere'
>>> only_lower_ascii_alpha(u"435 café")
u'caf'
22/10/2011 को 19:15
का स्रोत उपयोगकर्ता

वोट
0

व्यक्तिगत तौर पर मैं एक नियमित अभिव्यक्ति का प्रयोग करेंगे और उसके बाद लोअर केस में अंतिम स्ट्रिंग परिवर्तित करते हैं। मैं कैसे पायथन में यह लिखने के लिए पता नहीं है, लेकिन मूल विचार के लिए है:

  1. स्ट्रिंग में वर्णों को निकाल दें ताकि केस-संवेदी रेगुलर एक्सप्रेशन से मेल नहीं है " \w"
  2. लोअर केस को स्ट्रिंग में कनवर्ट करें

या ठीक इसके विपरीत।

12/03/2009 को 15:44
का स्रोत उपयोगकर्ता

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more