2015-06-09 6 views
7

को छोड़कर पाइथन स्ट्रिंग प्रतिस्थापन एक ऐसा फ़ंक्शन लिखना जो स्ट्रिंग के पहले अक्षर के प्रत्येक डुप्लिकेट चरित्र को प्रतिस्थापित करेगा * पहले अक्षर को छोड़कर - क्या यह इस से अधिक करने के लिए एक और पाइथोनिक/सुरुचिपूर्ण तरीका है (सूचियां, आदि?)?पहले वर्ण

def specialreplace(s): 
    firstchar = s[0] 
    modifiedstr = s[1:].replace(firstchar, "*") 
    print firstchar + modifiedstr 

specialreplace('oompaloompa') ---> o*mpal**mpa 
+1

कि सबसे अच्छा तरीका है [KISS सिद्धांत] के अनुसार (http://en.wikipedia.org/wiki तरह लग रहा है/KISS_principle)। आप इसका उपयोग क्यों नहीं करेंगे? –

+0

सोच रहा है कि इसके बारे में जाने के अन्य समान तरीके क्या हैं, यदि कोई हैं तो। सूचियों के साथ यह कैसे करेगा? – SpicyClubSauce

+0

आप गति के लिए स्ट्रिंग.ट्रांसलेट विधि भी नियोजित कर सकते हैं: https://docs.python.org/2/library/string.html लेकिन यह सबसे अच्छा तरीका है। इसके अलावा, गिरफ्तार विकास संदर्भ के लिए +1। –

उत्तर

1

आप पहले ही सूची अनुक्रमण और टुकड़ा कर रहे हैं, और आपके पास एक साफ जवाब है। फिर भी:

def specialreplace(s): 
    chars = [ ('*' if c == s[0] else c) for c in s[1:] ] 
    print s[0] + ''.join(chars) 

और आप codegolf करना चाहते हैं कि एक सा:

: इसे में एक डिफ़ॉल्ट वापसी मान वाला देखने शब्दकोश खोदते, क्योंकि क्यों पानी के नल का उपयोग नहीं के साथ

specialreplace = lambda s:s[0]+''.join(['*'if c==s[0]else c for c in s[1:]]) 

संपादित करें

specialreplace=lambda s:s[0]+''.join([{s[0]:'*'}.get(c,c)for c in s[1:]]) 

संपादित करें: @ Voo की टिप्पणी, सूची समझ यथोचित pythonic है - के रूप में SpicyClubSauce का अनुरोध किया है, तो आप Py के रूप में एक त्रिगुट ऑपरेटर के रूप में करीब है यदि आपके अक्षर सूची का उपयोग करना चाहिए थोन है, और एक साथ वापस पात्रों की सूची लाने के लिए शामिल हो गए हैं। लैम्ब्डा संस्करण बहुत ही अनियमित हैं। वे सभी प्रश्नकर्ता के मूल समाधान से कम सुरुचिपूर्ण हैं।

और मैं गति पर गलत था:

+0

उन दोनों में से कोई भी पोस्ट की तुलना में अधिक सुरुचिपूर्ण या अधिक पायथनिक नहीं है। – Voo

+0

यह ठीक है - मैंने बाद में टिप्पणी की कि मैं रचनात्मक विकल्पों का भी स्वागत करता हूं। – SpicyClubSauce

2

यहाँ जब तक आप iteratively, लेकिन एक और तरीका यह करने के लिए (प्रत्येक अक्षर, कई बार के लिए) यह कर रहे हैं, यह करने के लिए एक सिफारिश तरीका नहीं है। पायथन 3 में प्लस अलग है।

import string 
a = 'ababc' 
firstchar = a[0] 
trantab = string.maketrans(firstchar, '*') 

def translate(mystr, firschar): 
    trantab = string.maketrans(firstchar, '*') 
    return firstchar + string.translate(mystr[1:], trantab) 

def translate_iter(mystr, firschar, trantab): 
    return firstchar + string.translate(mystr[1:], trantab) 

def replace(mystr, firstchar): 
    return firstchar + mystr[1:].replace(firstchar, '*') 

In [29]: %timeit translate(a, firstchar) 
1000000 loops, best of 3: 582 ns per loop 

In [30]: %timeit replace(a, firstchar) 
1000000 loops, best of 3: 240 ns per loop 

In [32]: %timeit translate_iter(a, firstchar, trantab) 
1000000 loops, best of 3: 376 ns per loop 

संपादित करें: तारों पर शामिल होने का उपयोग न करें। इसका कोई कारण नहीं है।

import dis 
In [36]: def add(a,b): 
    return a+b 
    ....: 

In [37]: def join(a,b): 
    return join((a,b)) 
    ....: 

In [42]: dis.dis(add) 
    2   0 LOAD_FAST    0 (a) 
       3 LOAD_FAST    1 (b) 
       6 BINARY_ADD   
       7 RETURN_VALUE   

In [43]: dis.dis(join) 
    2   0 LOAD_GLOBAL    0 (join) 
       3 LOAD_FAST    0 (a) 
       6 LOAD_FAST    1 (b) 
       9 BUILD_TUPLE    2 
      12 CALL_FUNCTION   1 
      15 RETURN_VALUE 

आप एक व्यर्थ फ़ंक्शन कॉल कर रहे हैं जो कोई समझ में नहीं आता है, कोड को कम पठनीय बनाता है, और समग्र प्रदर्शन धीमा करता है।

मैं सभी पठनीयता के लिए प्रदर्शन बलिदान के लिए हूं, लेकिन जब यह प्रदर्शन और पठनीयता दोनों को त्याग नहीं करता है।

+0

गति आदमी को देखकर महान सामान! – SpicyClubSauce

5

यह एक साधारण समस्या है, मुझे यकीन नहीं है कि आप इसे जटिल करने का प्रयास क्यों कर रहे हैं। आपका समाधान अच्छा दिखता है, इस तथ्य को छोड़कर कि आपको स्ट्रिंग्स में एक साथ जुड़ने के लिए '+' के बजाय .join() का उपयोग करना चाहिए।

"".join((s[0], s[1:].replace(s[0], "*")) 
+0

नहीं, आपको शामिल होने का उपयोग नहीं करना चाहिए। यहां फ़ंक्शन कॉल करने का कोई कारण नहीं है। इसके लिए मेरा संपादन देखें। –

+0

@AlexanderHuszagh मुझे नहीं पता कि आपका मतलब 'मेरे संपादन' से क्या है, क्षमा करें। 'फ़ंक्शन कॉल' से आपका क्या मतलब है? कॉलिंग के छोटे ओवरहेड()? शामिल हों() _the_ idiom एक साथ तारों में शामिल होने के लिए है, जो हम यहां कर रहे हैं। – eiLHW

+0

इस पोस्ट पर संपादन देखें: http: // stackoverflow।कॉम/ए/30741141/4131059 मैं मूल रूप से dis.dis (कार्यों के लिए एक अजगर बाइटकोड विश्लेषक) का उपयोग यह निर्धारित करने के लिए करता हूं कि दोनों अलग-अलग कैसे होते हैं, इस प्रकार कोड को बाइट कोड में अनुवादित किया जाता है जिसे मशीन द्वारा चलाया जाता है। आपकी विधि को टुपल बनाने, फिर फ़ंक्शन को कॉल करने और फिर वास्तव में स्ट्रिंग में शामिल होने सहित कई चरणों की आवश्यकता होती है, जब "+" स्ट्रिंग में शामिल होता है। –

1

आपका कोड अच्छा लग रहा है और मुझे लगता है कि एक ही रास्ता है कि यह सुधार कर सकते हैं, कई अनुक्रमण की सवारी हो रही है, और उसके लिए आपको iter समारोह का उपयोग कर सकते पुनरावर्तक का समर्थन करने वाले next करने के लिए अपने स्ट्रिंग परिवर्तित करने के लिए:

def specialreplace(s): 
    it=iter(s) 
    first=next(it) 
    return first+''.join(['*' if i == first else i for i in it]) 
:
>>> def specialreplace(s): 
...  it=iter(s) 
...  first=next(it) 
...  return first+''.join(it).replace(first,'*') 
... 
>>> specialreplace(s) 
'o*mpal**mpa' 

इसके अलावा एक और विकल्प के रूप में आप एक सूची समझ और join साथ replace विधि की जगह ले सकता

निम्नलिखित बेंचमार्क का कहना है कि उनके बीच कोई अंतर नहीं है लेकिन दूसरा दृष्टिकोण थोड़ा बेहतर है।(1000000 पाश के लिए और नहीं एक लंबी स्ट्रिंग परीक्षण के लिए)

from timeit import timeit 

s1=""" 
def specialreplace(s): 
    firstchar = s[0] 
    modifiedstr = s[1:].replace(firstchar, "*") 
    print firstchar + modifiedstr 
""" 
s2=""" 
def specialreplace(s): 
    it=iter(s) 
    first=next(it) 
    return first+''.join(['*' if i == first else i for i in it]) 

    """ 

s3=""" 
def specialreplace(s): 
    it=iter(s) 
    first=next(it) 
    return first+''.join(it).replace(first,'*') 

    """ 

print ' first: ' ,timeit(stmt=s1, number=1000000) 
print 'second : ',timeit(stmt=s2, number=1000000)           
print '3rd : ',timeit(stmt=s3, number=1000000) 

परिणाम:

first: 0.0531640987396 
second : 0.0527780056 
3rd : 0.0523271560669 
+0

क्या आपने अपना कोड चलाया? –

+0

@ पैड्राइक कनिंघम हाँ मेरे पास है! क्यूं कर? – Kasramvd

+0

क्या आप अपने स्टीवी आश्चर्य चश्मा पहन रहे हैं? ;) अपना पहला फ़ंक्शन चलाएं और आउटपुट –

2

आप की गणना इस्तेमाल कर सकते हैं:

print("".join(["*" if s[i] == s[0] and i != 0 else ch for i, ch in enumerate(s)])) 

लेकिन वह सिर्फ मनोरंजन के लिए है, मैं छड़ी होगी अपने स्वयं के समाधान के साथ।

आप टिप्पणी का जवाब करने के लिए, आप के साथ कई पात्रों को बदलने के लिए कई मैपिंग का उपयोग कर सकते का अनुवाद:

print(s[0]+s[1:].translate((dict(zip((ord(s[0]),ord(s[2]),ord(s[3])),"*$!"))))) 
o*$!al**$!a 
:

from string import maketrans 
print(s[0]+s[1:].translate(maketrans(s[0]+s[2]+s[3],"*$!"))) 
o*$!al**$!a 

python3 में आप कुंजी के रूप में प्रत्येक चरित्र के ord का उपयोग कर एक मेज की जरूरत है

s = 'oompaloompa' 

from re import sub 

print(sub(r"(?<!^)"+s[0], "*", s)) 
o*mpal**mpa 

लेकिन एक:

तुम भी पहले वर्ण अनदेखी re.sub इस्तेमाल कर सकते हैं थोड़ा अधिक ओवरकिल हासिल करें।

0

यहाँ यह करने के लिए एक pythonic तरीका str.replace() विधि का उपयोग कर रहा है:

string_ = 'oompaloompa' 
new_string = string_[0]+string_.replace(string_[0],"*",string_.count(string_[0]))[1: 
0
def specialreplace(s): 
    return s[0]+s.replace(s[0],'*')[1:] 
+1

स्टैक ओवरव्लो में आपका स्वागत है। कृपया यह बताने पर विचार करें कि यह कोड स्निपेट मूल प्रश्न में बताई गई समस्या को हल करता है। –

संबंधित मुद्दे