मुझे पता है कि यह कैसे करना है अगर मैं स्ट्रिंग के सभी पात्रों के माध्यम से पुनरावृति करता हूं, लेकिन मैं अधिक सुरुचिपूर्ण विधि की तलाश कर रहा हूं।
जवाबों:
एक नियमित अभिव्यक्ति बहुत कम कोड के साथ चाल करेगी:
import re
...
if re.match("^[A-Za-z0-9_-]*$", my_little_string):
# do something here
\wशामिल हैं \dऔर _इसलिए isvalid = re.match(r'[\w-]+$', astr)या isinvalid = re.search(r'[^\w-]', astr)। locale.setlocaleया यूनिकोड स्ट्रिंग्स की एक संभावित उपस्थिति के लिए अतिरिक्त विचार की आवश्यकता होती है।
isvalid = re.match(r'[\w-]*$', astr)- खाली तार मान्य हैं।
[संपादित करें] अभी तक उल्लेखित एक और समाधान नहीं है, और यह अधिकांश मामलों में अब तक दिए गए अन्य लोगों से बेहतर प्रदर्शन करता है।
स्ट्रिंग में सभी मान्य वर्णों को बदलने के लिए string.translate का उपयोग करें, और देखें कि क्या हमारे पास कोई अमान्य अक्षर बचा है। यह बहुत तेज है क्योंकि यह काम करने के लिए अंतर्निहित सी फ़ंक्शन का उपयोग करता है, जिसमें बहुत कम अजगर बाइटकोड शामिल हैं।
स्पष्ट रूप से प्रदर्शन सब कुछ नहीं है - सबसे पठनीय समाधानों के लिए जाना संभवतः सबसे अच्छा तरीका है जब एक प्रदर्शन महत्वपूर्ण कोडपैथ में नहीं है, लेकिन यह देखने के लिए कि समाधान कैसे ढेर हो जाता है, यहां अब तक प्रस्तावित सभी तरीकों की प्रदर्शन तुलना है। check_trans string.translate पद्धति का उपयोग करने वाला है।
टेस्ट कोड:
import string, re, timeit
pat = re.compile('[\w-]*$')
pat_inv = re.compile ('[^\w-]')
allowed_chars=string.ascii_letters + string.digits + '_-'
allowed_set = set(allowed_chars)
trans_table = string.maketrans('','')
def check_set_diff(s):
return not set(s) - allowed_set
def check_set_all(s):
return all(x in allowed_set for x in s)
def check_set_subset(s):
return set(s).issubset(allowed_set)
def check_re_match(s):
return pat.match(s)
def check_re_inverse(s): # Search for non-matching character.
return not pat_inv.search(s)
def check_trans(s):
return not s.translate(trans_table,allowed_chars)
test_long_almost_valid='a_very_long_string_that_is_mostly_valid_except_for_last_char'*99 + '!'
test_long_valid='a_very_long_string_that_is_completely_valid_' * 99
test_short_valid='short_valid_string'
test_short_invalid='/$%$%&'
test_long_invalid='/$%$%&' * 99
test_empty=''
def main():
funcs = sorted(f for f in globals() if f.startswith('check_'))
tests = sorted(f for f in globals() if f.startswith('test_'))
for test in tests:
print "Test %-15s (length = %d):" % (test, len(globals()[test]))
for func in funcs:
print " %-20s : %.3f" % (func,
timeit.Timer('%s(%s)' % (func, test), 'from __main__ import pat,allowed_set,%s' % ','.join(funcs+tests)).timeit(10000))
print
if __name__=='__main__': main()
मेरे सिस्टम पर परिणाम हैं:
Test test_empty (length = 0):
check_re_inverse : 0.042
check_re_match : 0.030
check_set_all : 0.027
check_set_diff : 0.029
check_set_subset : 0.029
check_trans : 0.014
Test test_long_almost_valid (length = 5941):
check_re_inverse : 2.690
check_re_match : 3.037
check_set_all : 18.860
check_set_diff : 2.905
check_set_subset : 2.903
check_trans : 0.182
Test test_long_invalid (length = 594):
check_re_inverse : 0.017
check_re_match : 0.015
check_set_all : 0.044
check_set_diff : 0.311
check_set_subset : 0.308
check_trans : 0.034
Test test_long_valid (length = 4356):
check_re_inverse : 1.890
check_re_match : 1.010
check_set_all : 14.411
check_set_diff : 2.101
check_set_subset : 2.333
check_trans : 0.140
Test test_short_invalid (length = 6):
check_re_inverse : 0.017
check_re_match : 0.019
check_set_all : 0.044
check_set_diff : 0.032
check_set_subset : 0.037
check_trans : 0.015
Test test_short_valid (length = 18):
check_re_inverse : 0.125
check_re_match : 0.066
check_set_all : 0.104
check_set_diff : 0.051
check_set_subset : 0.046
check_trans : 0.017
अनुवाद का दृष्टिकोण ज्यादातर मामलों में सबसे अच्छा लगता है, इसलिए नाटकीय रूप से लंबे वैध तार के साथ, लेकिन test_long_invalid में regexes द्वारा पीटा जाता है (संभवतः क्योंकि regex तुरंत बाहर निकल सकता है, लेकिन अनुवाद को हमेशा पूरे स्ट्रिंग को स्कैन करना पड़ता है)। सेट अप दृष्टिकोण आमतौर पर सबसे खराब होते हैं, केवल खाली स्ट्रिंग मामले के लिए रेगीक्स को पीटना।
सभी का उपयोग करना (एक्स फॉर एस में एक्स के लिए allow_set) अच्छा प्रदर्शन करता है अगर यह जल्दी से बाहर निकलता है, लेकिन बुरा हो सकता है अगर इसे हर चरित्र के माध्यम से पुनरावृत्त करना है। isSubSet और सेट अंतर तुलनीय हैं, और डेटा की परवाह किए बिना स्ट्रिंग की लंबाई के लिए लगातार आनुपातिक हैं।
सभी मान्य वर्णों के मिलान और अमान्य वर्णों की खोज करने के लिए रेगेक्स विधियों के बीच समान अंतर है। लंबे समय तक जांच करने पर मिलान करना थोड़ा बेहतर होता है, लेकिन पूरी तरह से वैध स्ट्रिंग, लेकिन स्ट्रिंग के अंत के पास अमान्य वर्णों के लिए बदतर।
string.ascii_letters, string.lettersतो इसके बजाय का उपयोग करें (अन्यथा आप में झूठे सकारात्मक परिणाम प्राप्त कर सकते हैं check_trans()। string.maketrans()यूनिकोड स्ट्रिंग्स के लिए काम नहीं करेंगे।
from __future__ import unicode_literals) के लिए, उपयोग trans_table3 = dict((ord(char), '') for char in allowed_chars)और डीफ़ check_trans(s): return not s.translate(trans_table3)। लेकिन सामान्य तौर पर, यह आरई संस्करणों से भी बदतर प्रदर्शन करता है।
इस लक्ष्य को प्राप्त करने के कई तरीके हैं, कुछ दूसरों की तुलना में स्पष्ट हैं। मेरे प्रत्येक उदाहरण के लिए, 'ट्रू' का अर्थ है कि पारित स्ट्रिंग मान्य है, 'गलत' का अर्थ है कि इसमें अमान्य वर्ण हैं।
सबसे पहले, वहाँ भोली दृष्टिकोण है:
import string
allowed = string.letters + string.digits + '_' + '-'
def check_naive(mystring):
return all(c in allowed for c in mystring)
फिर एक नियमित अभिव्यक्ति का उपयोग होता है, आप इसे re.match () के साथ कर सकते हैं। ध्यान दें कि '-' के अंत में होना चाहिए] अन्यथा इसका उपयोग 'रेंज' सीमांकक के रूप में किया जाएगा। उस $ को भी नोट करें जिसका अर्थ है 'स्ट्रिंग का अंत'। इस प्रश्न में दिए गए अन्य उत्तर एक विशेष चरित्र वर्ग, '\ w' का उपयोग करते हैं, मैं हमेशा [] का उपयोग करते हुए एक स्पष्ट वर्ण वर्ग श्रेणी का उपयोग करना पसंद करता हूं, क्योंकि एक त्वरित संदर्भ गाइड को देखने के बिना समझना आसान है, और विशेष के लिए आसान है- मामला।
import re
CHECK_RE = re.compile('[a-zA-Z0-9_-]+$')
def check_re(mystring):
return CHECK_RE.match(mystring)
एक अन्य समाधान ने नोट किया कि आप नियमित अभिव्यक्ति के साथ एक उलटा मैच कर सकते हैं, मैंने इसे अब यहां शामिल किया है। ध्यान दें कि [^ ...] वर्ण वर्ग को प्रभावित करता है क्योंकि ^ का उपयोग किया जाता है:
CHECK_INV_RE = re.compile('[^a-zA-Z0-9_-]')
def check_inv_re(mystring):
return not CHECK_INV_RE.search(mystring)
आप 'सेट' ऑब्जेक्ट के साथ कुछ मुश्किल भी कर सकते हैं। इस उदाहरण पर एक नज़र डालें, जो मूल स्ट्रिंग से हटाए जाने वाले सभी वर्णों को हटा देता है, हमें एक सेट के साथ छोड़कर) क कुछ भी नहीं है, या ख) स्ट्रिंग से अपमानजनक वर्ण:
def check_set(mystring):
return not set(mystring) - set(allowed)
string.ascii_lettersअगर आप '[a-zA-Z]' regexps का उपयोग करें।
यदि यह डैश और अंडरस्कोर के लिए नहीं था, तो सबसे आसान समाधान होगा
my_little_string.isalnum()
( पायथन लाइब्रेरी संदर्भ की धारा 3.6.1 )
नियमित अभिव्यक्ति बहुत लचीली हो सकती है।
import re;
re.fullmatch("^[\w-]+$", target_string) # fullmatch looks also workable for python 3.4
\w: केवल [a-zA-Z0-9_]
इसलिए आपको -हाइफ़न चार को सही ठहराने के लिए चार जोड़ना होगा ।
+: पूर्ववर्ती चार्ट के एक या अधिक दोहराव का मिलान करें। मुझे लगता है कि आप रिक्त इनपुट को स्वीकार नहीं करते हैं। लेकिन अगर आप ऐसा करते हैं, तो बदलिए *।
^: स्ट्रिंग की शुरुआत से मेल खाता है।
$: स्ट्रिंग के अंत से मेल खाता है।
आपको इन दो विशेष पात्रों की आवश्यकता है क्योंकि आपको निम्नलिखित मामले से बचने की आवश्यकता है। यहाँ के अनचाहे वर्ण &मिलान पैटर्न के बीच दिखाई दे सकते हैं।
&&&PATTERN&&PATTERN
वैसे आप रेगेक्स की मदद पूछ सकते हैं, यहाँ महान :)
कोड:
import re
string = 'adsfg34wrtwe4r2_()' #your string that needs to be matched.
regex = r'^[\w\d_()]*$' # you can also add a space in regex if u want to allow it in the string
if re.match(regex,string):
print 'yes'
else:
print 'false'
आउटपुट:
yes
उम्मीद है की यह मदद करेगा :)
आप हमेशा एक सूची समझ का उपयोग कर सकते हैं और सभी के साथ परिणामों की जांच कर सकते हैं, यह रेगेक्स का उपयोग करने की तुलना में थोड़ा कम संसाधन गहन होगा: all([c in string.letters + string.digits + ["_", "-"] for c in mystring])
यहाँ जेरब के "भोले दृष्टिकोण" पर आधारित कुछ है (भोले उनके शब्द हैं, मेरा नहीं!)।
import string
ALLOWED = frozenset(string.ascii_letters + string.digits + '_' + '-')
def check(mystring):
return all(c in ALLOWED for c in mystring)
अगर ALLOWEDएक तार था, तो मुझे लगता है कि c in ALLOWEDजब तक यह एक मैच नहीं मिला या अंत तक नहीं पहुंचा, तब तक स्ट्रिंग में प्रत्येक चरित्र पर पुनरावृति शामिल होगी। जोएल स्पोल्स्की को उद्धृत करने के लिए, एक शलेमियल द पेंटर एल्गोरिथम का कुछ है ।
लेकिन एक सेट में अस्तित्व के लिए परीक्षण अधिक कुशल होना चाहिए, या अनुमत वर्णों की संख्या पर कम से कम निर्भर होना चाहिए। निश्चित रूप से यह दृष्टिकोण मेरी मशीन पर थोड़ा तेज है। यह स्पष्ट है और मुझे लगता है कि यह ज्यादातर मामलों के लिए पर्याप्त रूप से अच्छा प्रदर्शन करता है (मेरी धीमी मशीन पर मैं एक सेकंड के एक अंश में हजारों शॉर्ट-ईश स्ट्रिंग्स को मान्य कर सकता हूं)। मुझें यह पसंद है।
वास्तव में मेरी मशीन पर एक regexp कई बार तेजी से काम करता है, और यह इस तरह से सरल है (यकीनन सरल)। ताकि शायद आगे का सबसे अच्छा तरीका हो।
एक regex का उपयोग करें और देखें कि क्या यह मेल खाता है!
([a-z][A-Z][0-9]\_\-)*