हजारों विभाजक के रूप में अल्पविराम के साथ संख्या कैसे प्रिंट करें?


752

मैं हजारों विभाजकों के रूप में अल्पविराम के साथ अजगर 2.6.1 में एक पूर्णांक मुद्रित करने का प्रयास कर रहा हूं । उदाहरण के लिए, मैं नंबर प्रदर्शित करना चाहते 1234567के रूप में 1,234,567। मैं ऐसा कैसे कर पाऊंगा? मैंने Google पर कई उदाहरण देखे हैं, लेकिन मैं सबसे सरल व्यावहारिक तरीका ढूंढ रहा हूं।

अवधि और अल्पविराम के बीच निर्णय लेने के लिए इसे स्थानीय-विशिष्ट होने की आवश्यकता नहीं है। मैं यथोचित रूप से सरल रूप में कुछ पसंद करूंगा।

जवाबों:


1737

लोकेल अनजान

'{:,}'.format(value)  # For Python ≥2.7
f'{value:,}'  # For Python ≥3.6

लोकलाज से अवगत कराया

import locale
locale.setlocale(locale.LC_ALL, '')  # Use '' for auto, or force e.g. to 'en_US.UTF-8'

'{:n}'.format(value)  # For Python ≥2.7
f'{value:n}'  # For Python ≥3.6

संदर्भ

प्रति प्रारूप विशिष्टता मिनी भाषा ,

','विकल्प के लिए एक हज़ार विभाजक के लिए एक अल्पविराम के उपयोग के संकेत देती है। एक स्थानीय जागरूक विभाजक के लिए, 'n'इसके बजाय पूर्णांक प्रस्तुति प्रकार का उपयोग करें।


24
ध्यान दें कि यह अमेरिका और कुछ अन्य स्थानों के बाहर सही नहीं होगा, उस स्थिति में चुना गया locale.format () सही उत्तर है।
ग्रिंगो सुवे

10
कीवर्ड {val:,}.format(val=val)
लॉजिक

11
बहुत धन्यवाद। धन राशियों के लिए, 2 दशमलव स्थानों के साथ - "{:, 2f}"। स्वरूप (मान)
dlink

3
पुर्तगाल के लिए जहां हम एक विभाजक के रूप में बिंदु (।) का उपयोग करते हैं: {:,} "। format (मान) .replace (',', ','।)

13
अजगर 3.6 और ऊपर में, एफ-स्ट्रिंग्स और भी अधिक सुविधा जोड़ते हैं। जैसेf"{2 ** 64 - 1:,}"
CJ Gaconnet

285

मुझे यह काम करने के लिए मिला:

>>> import locale
>>> locale.setlocale(locale.LC_ALL, 'en_US')
'en_US'
>>> locale.format("%d", 1255000, grouping=True)
'1,255,000'

निश्चित रूप से, आपको अंतर्राष्ट्रीयकरण समर्थन की आवश्यकता नहीं है , लेकिन यह स्पष्ट, संक्षिप्त है, और एक अंतर्निहित पुस्तकालय का उपयोग करता है।

PS वह "% d" सामान्य%-स्वरूपक है। आपके पास केवल एक ही फ़ॉर्मेटर हो सकता है, लेकिन फ़ील्ड चौड़ाई और सटीक सेटिंग्स के संदर्भ में आपको जो कुछ भी चाहिए वह हो सकता है।

PPS यदि आपको localeकाम नहीं मिल रहा है, तो मैं मार्क के उत्तर के संशोधित संस्करण का सुझाव दूंगा:

def intWithCommas(x):
    if type(x) not in [type(0), type(0L)]:
        raise TypeError("Parameter must be an integer.")
    if x < 0:
        return '-' + intWithCommas(-x)
    result = ''
    while x >= 1000:
        x, r = divmod(x, 1000)
        result = ",%03d%s" % (r, result)
    return "%d%s" % (x, result)

नकारात्मक स्थिति के लिए पुनरावृत्ति उपयोगी है, लेकिन प्रति कॉमा प्रति एक प्रति मुझे थोड़ा अधिक लगता है।


14
मैंने आपका कोड आज़माया, और दुर्भाग्य से, मुझे यह मिल गया: "locale.Error: unsupported locale setting"। : -s
मार्क बायर्स

11
मार्क: यदि आप लिनक्स पर हैं, तो आप अपने /etc/locale.gen, या जो कुछ भी आपके glibc का उपयोग कर रहा है, उसका लोकेशन बनाने के लिए देखना चाहते हैं। आप "" en "," en_US.utf8 "," en_US.UTF-8 ", 'en_UK" (sp?), आदि माइक भी आज़माना चाह सकते हैं: एक पुस्तक होने की आवश्यकता है: "PEP: मैंने चिंता करना और प्रेम को रोकने के लिए कैसे जानें docs.python.org। " मैंने पायथन 1.5.6 के आसपास के सभी पुस्तकालयों को याद करना छोड़ दिया। के रूप में locale, मैं इसे के रूप में मैं कर सकता हूँ के रूप में कम का उपयोग करें।
माइक डीस्मोन

10
आप setlocaleडिफ़ॉल्ट का उपयोग करने के लिए '' का उपयोग कर सकते हैं , जो उम्मीद है कि उचित होगा।
मार्क रैनसम

24
इसे आज़माएँ: locale.setlocale (locale.LC_ALL, '') इसने मेरे लिए काम किया
नादिया आलमर्ली

1
हालांकि चतुर, मुझे ऐसे फ़ंक्शन पसंद नहीं हैं जो वैश्विक सेटिंग बनाते हैं ... 'blah'.format () का उपयोग करना बेहतर तरीका है।
सेरिन

132

अक्षमता और अपठनीयता के लिए हराना मुश्किल है:

>>> import itertools
>>> s = '-1234567'
>>> ','.join(["%s%s%s" % (x[0], x[1] or '', x[2] or '') for x in itertools.izip_longest(s[::-1][::3], s[::-1][1::3], s[::-1][2::3])])[::-1].replace('-,','-')

171
इस प्रश्न का उत्तर देने के लिए सबसे अक्षम और अपठनीय विधि के लिए वोट किया गया।
psytek

1
अच्छा होगा अगर यह कम से कम काम करेगा। इस संख्या को "17371830" आज़माएं, यह "173.718.3.0" =) हो जाता है
होम्स

5
काल? यह भी संभव नहीं है, होम्स। कबाड़ का यह टुकड़ा पूरी तरह से लोकेल को अनदेखा करता है। मुझे आश्चर्य है कि आपको वह परिणाम कैसे मिला। आपका उदाहरण मेरे लिए '17, 371,830 'का उत्पादन करता है।
केसी किर्कम

11
इसे एक फंक्शन बनाने के लिए मैं सुझाव दूंगा: lambda x: (lambda s: ','.join(["%s%s%s" % (x[0], x[1] or '', x[2] or '') for x in itertools.izip_longest(s[::-1][::3], s[::-1][1::3], s[::-1][2::3])])[::-1].replace('-,','-'))(str(x))सिर्फ ऑबफ्यूजन थीम रखने के लिए।
क्वांटम

95

अप्रासंगिक भागों को हटाने और इसे थोड़ा साफ करने के बाद यहां स्थानीय समूहन कोड दिया गया है:

(निम्नलिखित केवल पूर्णांक के लिए काम करता है)

def group(number):
    s = '%d' % number
    groups = []
    while s and s[-1].isdigit():
        groups.append(s[-3:])
        s = s[:-3]
    return s + ','.join(reversed(groups))

>>> group(-23432432434.34)
'-23,432,432,434'

यहाँ पहले से ही कुछ अच्छे उत्तर हैं। मैं भविष्य के संदर्भ के लिए इसे जोड़ना चाहता हूं। अजगर 2.7 में हजारों विभाजक के लिए एक प्रारूप विनिर्देशक होने जा रहा है। अजगर डॉक्स के अनुसार यह इस तरह काम करता है

>>> '{:20,.2f}'.format(f)
'18,446,744,073,709,551,616.00'

Python3.1 में आप इस तरह से काम कर सकते हैं:

>>> format(1234567, ',d')
'1,234,567'

हाँ, कठिन तरीके मुख्य रूप से पुराने पायथन पर लोगों के लिए हैं, जैसे कि आरएचईएल और अन्य दीर्घकालिक समर्थन डिस्ट्रोस के साथ भेज दिया गया।
माइक डीमोन

3
प्रारूप स्ट्रिंग के साथ इसे कैसे व्यक्त करें? "%, d"% 1234567 काम नहीं करता है
फ्रेडरिक बाजिन

91

मुझे आश्चर्य है कि किसी ने भी यह उल्लेख नहीं किया है कि आप पायथन 3.6 में एफ-स्ट्रिंग्स के साथ ऐसा कर सकते हैं:

>>> num = 10000000
>>> print(f"{num:,}")
10,000,000

... जहां बृहदान्त्र के बाद का हिस्सा प्रारूप निर्दिष्ट होता है। अल्पविराम आप चाहते हैं विभाजक चरित्र है, इसलिए f"{num:_}"अल्पविराम के बजाय अंडरस्कोर का उपयोग करता है।

यह format(num, ",")अजगर 3 के पुराने संस्करणों के लिए उपयोग करने के बराबर है ।


39

यहां एक-पंक्ति रेगेक्स प्रतिस्थापन है:

re.sub("(\d)(?=(\d{3})+(?!\d))", r"\1,", "%d" % val)

केवल अकुशल आउटपुट के लिए काम करता है:

import re
val = 1234567890
re.sub("(\d)(?=(\d{3})+(?!\d))", r"\1,", "%d" % val)
# Returns: '1,234,567,890'

val = 1234567890.1234567890
# Returns: '1,234,567,890'

या 4 अंकों से कम वाले झांकियों के लिए, प्रारूप का प्रारूप बदलें %.3f:

re.sub("(\d)(?=(\d{3})+(?!\d))", r"\1,", "%.3f" % val)
# Returns: '1,234,567,890.123'

NB: तीन से अधिक दशमलव अंकों के साथ सही ढंग से काम नहीं करता क्योंकि यह दशमलव भाग को समूह बनाने का प्रयास करेगा:

re.sub("(\d)(?=(\d{3})+(?!\d))", r"\1,", "%.5f" % val)
# Returns: '1,234,567,890.12,346'

यह काम किस प्रकार करता है

चलो इसे तोड़ दो:

re.sub(pattern, repl, string)

pattern = \
    "(\d)           # Find one digit...
     (?=            # that is followed by...
         (\d{3})+   # one or more groups of three digits...
         (?!\d)     # which are not followed by any more digits.
     )",

repl = \
    r"\1,",         # Replace that one digit by itself, followed by a comma,
                    # and continue looking for more matches later in the string.
                    # (re.sub() replaces all matches it finds in the input)

string = \
    "%d" % val      # Format the string as a decimal to begin with

1
वर्बोज़ मोड का उपयोग करें और आप कोड के अंदर सही टिप्पणी कर सकते हैं
डैनियल स्ट्रैकोबोको

क्या आप "" (?! D) को "$" से बदल नहीं सकते थे?
GL2014

28

यह मैं तैरने के लिए करता हूं। हालांकि, ईमानदारी से, मुझे यकीन नहीं है कि यह किस संस्करण के लिए काम करता है - मैं 2.7 का उपयोग कर रहा हूं:

my_number = 4385893.382939491

my_string = '{:0,.2f}'.format(my_number)

रिटर्न: 4,385,893.38

अद्यतन: मेरे पास हाल ही में इस प्रारूप के साथ एक मुद्दा था (आपको सटीक कारण नहीं बता सकता), लेकिन इसे हटाकर इसे ठीक करने में सक्षम था 0:

my_string = '{:,.2f}'.format(my_number)

19

आप '{:n}'.format( value )स्थानीय प्रतिनिधित्व के लिए भी उपयोग कर सकते हैं । मुझे लगता है कि स्थानीय समाधान के लिए यह सबसे सरल तरीका है।

अधिक जानकारी के लिए thousands, पायथन डीओसी में खोजें

मुद्रा के लिए, आप locale.currencyध्वज को सेट करके उपयोग कर सकते हैं grouping:

कोड

import locale

locale.setlocale( locale.LC_ALL, '' )
locale.currency( 1234567.89, grouping = True )

उत्पादन

'Portuguese_Brazil.1252'
'R$ 1.234.567,89'

13

इयान श्नाइडर के उत्तर का थोड़ा विस्तार:

यदि आप एक कस्टम हजारों विभाजक का उपयोग करना चाहते हैं, तो सबसे सरल उपाय है:

'{:,}'.format(value).replace(',', your_custom_thousands_separator)

उदाहरण

'{:,.2f}'.format(123456789.012345).replace(',', ' ')

यदि आप इस तरह से जर्मन प्रतिनिधित्व चाहते हैं, तो यह थोड़ा और अधिक जटिल हो जाता है:

('{:,.2f}'.format(123456789.012345)
          .replace(',', ' ')  # 'save' the thousands separators 
          .replace('.', ',')  # dot to comma
          .replace(' ', '.')) # thousand separators to dot

थोड़ा छोटा:'{:_.2f}'.format(12345.6789).replace('.', ',').replace('_', '.')
टॉम

12

मुझे यकीन है कि इसके लिए एक मानक पुस्तकालय समारोह होना चाहिए, लेकिन यह अपने आप को पुनरावृत्ति का उपयोग करके लिखने का प्रयास करने के लिए मज़ेदार था, इसलिए यहां मेरे साथ आया था:

def intToStringWithCommas(x):
    if type(x) is not int and type(x) is not long:
        raise TypeError("Not an integer!")
    if x < 0:
        return '-' + intToStringWithCommas(-x)
    elif x < 1000:
        return str(x)
    else:
        return intToStringWithCommas(x / 1000) + ',' + '%03d' % (x % 1000)

यह कहने के बाद कि, यदि कोई व्यक्ति इसे करने के लिए एक मानक तरीका ढूंढता है, तो आपको इसके बजाय इसका उपयोग करना चाहिए।


दुर्भाग्य से सभी मामलों में काम नहीं करता है। intToStringWithCommas (1000.1) -> '1.0001,000'
नादिया अलरामली

उन्होंने विशेष रूप से पूर्णांकों को कहा और यह जितना संभव हो उतना सरल होना चाहिए, इसलिए मैंने पूर्णांकों के अलावा डेटाटाइप्स को नहीं संभालने का फैसला किया। मैंने फ़ंक्शन नाम _int_ToStringWithCommas में भी इसे स्पष्ट किया है। अब मैंने इसे और अधिक स्पष्ट करने के लिए एक वृद्धि भी जोड़ दी है।
मार्क बायर्स

8

से टिप्पणी activestate नुस्खा करने के लिए 498,181 मैं इस पर फिर से काम:

import re
def thous(x, sep=',', dot='.'):
    num, _, frac = str(x).partition(dot)
    num = re.sub(r'(\d{3})(?=\d)', r'\1'+sep, num[::-1])[::-1]
    if frac:
        num += dot + frac
    return num

यह नियमित अभिव्यक्ति की सुविधा का उपयोग करता है: लुकहेड यानी (?=\d)केवल तीन अंकों के समूहों को, जिन्हें 'एक अल्पविराम प्राप्त करने के बाद एक अंक' मिलता है। मैं 'के बाद' कहता हूं क्योंकि इस बिंदु पर स्ट्रिंग रिवर्स है।

[::-1] बस एक स्ट्रिंग उलट देता है।


8

स्वीकृत उत्तर ठीक है, लेकिन मैं वास्तव में पसंद करता हूं format(number,',')। मेरे लिए व्याख्या और याद रखना आसान है।

https://docs.python.org/3/library/functions.html#format


पूरी तरह से काम करता है, फ़्लोट के लिए बहुत से दशमलव अंक प्रदर्शित करने से भी बचता है।
Rexcirus

7

अजगर ३

-

पूर्णांक (दशमलव के बिना):

"{:,d}".format(1234567)

-

फ़्लोट्स (दशमलव के साथ):

"{:,.2f}".format(1234567)

जहां fदशमलव संख्या की संख्या निर्दिष्ट करने से पहले संख्या।

-

बक्शीश

भारतीय लाख / करोड़ की संख्या प्रणाली (12,34,567) के लिए त्वरित और गंदे स्टार्टर फ़ंक्शन:

https://stackoverflow.com/a/44832241/4928578


5

पायथन संस्करण 2.6 से आप यह कर सकते हैं:

def format_builtin(n):
    return format(n, ',')

पायथन संस्करणों के लिए <2.6 और सिर्फ आपकी जानकारी के लिए, यहां 2 मैनुअल समाधान हैं, वे फ्लोट को किलों में बदल देते हैं लेकिन नकारात्मक संख्याएं सही तरीके से काम करती हैं:

def format_number_using_lists(number):
    string = '%d' % number
    result_list = list(string)
    indexes = range(len(string))
    for index in indexes[::-3][1:]:
        if result_list[index] != '-':
            result_list.insert(index+1, ',')
    return ''.join(result_list)

यहाँ ध्यान देने योग्य कुछ बातें:

  • यह पंक्ति: string = '% d'% संख्या खूबसूरती से एक स्ट्रिंग को एक संख्या में परिवर्तित करती है, यह नकारात्मक का समर्थन करती है और यह फ्लोट्स से अंशों को गिराती है, जिससे उन्हें इन्टास होता है;
  • यह स्लाइस इंडेक्स [:: - 3] अंत से शुरू होने वाले प्रत्येक तीसरे आइटम को लौटाता है, इसलिए मैंने बहुत ही अंतिम आइटम क्यूज को निकालने के लिए एक और स्लाइस [1:] का उपयोग किया है मुझे अंतिम संख्या के बाद अल्पविराम की आवश्यकता नहीं है;
  • यह सशर्त यदि l [अनुक्रमणिका]! = '-' का उपयोग ऋणात्मक संख्याओं का समर्थन करने के लिए किया जा रहा है, तो ऋण चिह्न के बाद अल्पविराम न डालें।

और अधिक कट्टर संस्करण:

def format_number_using_generators_and_list_comprehensions(number):
    string = '%d' % number
    generator = reversed( 
        [
            value+',' if (index!=0 and value!='-' and index%3==0) else value
            for index,value in enumerate(reversed(string))
        ]
    )
    return ''.join(generator)

2

मैं एक पायथन शुरुआत करने वाला हूं, लेकिन एक अनुभवी प्रोग्रामर हूं। मेरे पास पायथन 3.5 है, इसलिए मैं सिर्फ कॉमा का उपयोग कर सकता हूं, लेकिन फिर भी यह एक दिलचस्प प्रोग्रामिंग अभ्यास है। अहस्ताक्षरित पूर्णांक के मामले पर विचार करें। हजारों विभाजकों को जोड़ने के लिए सबसे पठनीय पायथन कार्यक्रम प्रतीत होता है:

def add_commas(instr):
    out = [instr[0]]
    for i in range(1, len(instr)):
        if (len(instr) - i) % 3 == 0:
            out.append(',')
        out.append(instr[i])
    return ''.join(out)

सूची बोध का उपयोग करना भी संभव है:

add_commas(instr):
    rng = reversed(range(1, len(instr) + (len(instr) - 1)//3 + 1))
    out = [',' if j%4 == 0 else instr[-(j - j//4)] for j in rng]
    return ''.join(out)

यह छोटा है, और एक लाइनर हो सकता है, लेकिन आपको यह समझने के लिए कुछ मानसिक जिम्नास्टिक करना होगा कि यह क्यों काम करता है। दोनों ही मामलों में हमें:

for i in range(1, 11):
    instr = '1234567890'[:i]
    print(instr, add_commas(instr))
1 1
12 12
123 123
1234 1,234
12345 12,345
123456 123,456
1234567 1,234,567
12345678 12,345,678
123456789 123,456,789
1234567890 1,234,567,890

पहला संस्करण अधिक समझदार विकल्प है, यदि आप चाहते हैं कि कार्यक्रम को समझा जाए।


1

यहाँ एक है जो फ़्लोट के लिए भी काम करता है:

def float2comma(f):
    s = str(abs(f)) # Convert to a string
    decimalposition = s.find(".") # Look for decimal point
    if decimalposition == -1:
        decimalposition = len(s) # If no decimal, then just work from the end
    out = "" 
    for i in range(decimalposition+1, len(s)): # do the decimal
        if not (i-decimalposition-1) % 3 and i-decimalposition-1: out = out+","
        out = out+s[i]      
    if len(out):
        out = "."+out # add the decimal point if necessary
    for i in range(decimalposition-1,-1,-1): # working backwards from decimal point
        if not (decimalposition-i-1) % 3 and decimalposition-i-1: out = ","+out
        out = s[i]+out      
    if f < 0:
        out = "-"+out
    return out

उपयोग उदाहरण:

>>> float2comma(10000.1111)
'10,000.111,1'
>>> float2comma(656565.122)
'656,565.122'
>>> float2comma(-656565.122)
'-656,565.122'

1
float2comma(12031023.1323)रिटर्न: '12, 031,023.132,3 '
demux

1

पायथन 2.5+ और पायथन 3 के लिए एक लाइनर (केवल सकारात्मक इंट):

''.join(reversed([x + (',' if i and not i % 3 else '') for i, x in enumerate(reversed(str(1234567)))]))

1

सार्वभौमिक समाधान

मुझे पिछले शीर्ष मतदान उत्तरों में डॉट विभाजक के साथ कुछ मुद्दे मिले हैं। मैंने एक सार्वभौमिक समाधान तैयार किया है जहां आप लोकेल को संशोधित किए बिना एक हजार विभाजक के रूप में जो चाहें उपयोग कर सकते हैं । मुझे पता है कि यह सबसे सुरुचिपूर्ण समाधान नहीं है, लेकिन यह काम पूरा करता है। इसे सुधारने के लिए स्वतंत्र महसूस करें!

def format_integer(number, thousand_separator='.'):
    def reverse(string):
        string = "".join(reversed(string))
        return string

    s = reverse(str(number))
    count = 0
    result = ''
    for char in s:
        count = count + 1
        if count % 3 == 0:
            if len(s) == count:
                result = char + result
            else:
                result = thousand_separator + char + result
        else:
            result = char + result
    return result


print(format_integer(50))
# 50
print(format_integer(500))
# 500
print(format_integer(50000))
# 50.000
print(format_integer(50000000))
# 50.000.000

0

यह कॉमा के साथ पैसा भी करता है

def format_money(money, presym='$', postsym=''):
    fmt = '%0.2f' % money
    dot = string.find(fmt, '.')
    ret = []
    if money < 0 :
        ret.append('(')
        p0 = 1
    else :
        p0 = 0
    ret.append(presym)
    p1 = (dot-p0) % 3 + p0
    while True :
        ret.append(fmt[p0:p1])
        if p1 == dot : break
        ret.append(',')
        p0 = p1
        p1 += 3
    ret.append(fmt[dot:])   # decimals
    ret.append(postsym)
    if money < 0 : ret.append(')')
    return ''.join(ret)

0

मेरे पास इस कोड का एक अजगर 2 और अजगर 3 संस्करण है। मुझे पता है कि यह प्रश्न अजगर 2 के लिए पूछा गया था, लेकिन अब (8 साल बाद योग्य) लोग संभवतः अजगर का उपयोग कर रहे होंगे 3.

पायथन 3 कोड:

import random
number = str(random.randint(1, 10000000))
comma_placement = 4
print('The original number is: {}. '.format(number))
while True:
    if len(number) % 3 == 0:
        for i in range(0, len(number) // 3 - 1):
            number = number[0:len(number) - comma_placement + 1] + ',' + number[len(number) - comma_placement + 1:]
            comma_placement = comma_placement + 4
    else:
        for i in range(0, len(number) // 3):
            number = number[0:len(number) - comma_placement + 1] + ',' + number[len(number) - comma_placement + 1:]
    break
print('The new and improved number is: {}'.format(number))        


पायथन 2 कोड: (संपादित करें। अजगर 2 कोड काम नहीं कर रहा है। मैं सोच रहा हूं कि वाक्यविन्यास अलग है)।

import random
number = str(random.randint(1, 10000000))
comma_placement = 4
print 'The original number is: %s.' % (number)
while True:
    if len(number) % 3 == 0:
        for i in range(0, len(number) // 3 - 1):
            number = number[0:len(number) - comma_placement + 1] + ',' + number[len(number) - comma_placement + 1:]
            comma_placement = comma_placement + 4
    else:
        for i in range(0, len(number) // 3):
            number = number[0:len(number) - comma_placement + 1] + ',' + number[len(number) - comma_placement + 1:]
    break
print 'The new and improved number is: %s.' % (number) 

0

मैं अजगर 2.5 का उपयोग कर रहा हूं, इसलिए मुझे अंतर्निहित स्वरूपण तक पहुंच नहीं है।

मैंने Django कोड intcomma (नीचे दिए गए कोड में intcomma_recurs) को देखा और महसूस किया कि यह अक्षम है, क्योंकि यह पुनरावर्ती है और प्रत्येक रन पर regex को संकलित करना भी अच्छी बात नहीं है। यह आवश्यक नहीं है कि एक 'मुद्दा' हो क्योंकि django वास्तव में इस तरह के निम्न-स्तरीय प्रदर्शन पर ध्यान केंद्रित नहीं करता है। साथ ही, मुझे प्रदर्शन में 10 अंतर के कारक की उम्मीद थी, लेकिन यह केवल 3 गुना धीमी है।

जिज्ञासा से बाहर मैंने यह देखने के लिए intcomma के कुछ संस्करणों को लागू किया कि regex का उपयोग करते समय प्रदर्शन के फायदे क्या हैं। मेरा परीक्षण डेटा इस कार्य के लिए एक मामूली लाभ है, लेकिन आश्चर्यजनक रूप से बहुत अधिक नहीं है।

मुझे यह देखकर भी खुशी हुई कि मुझे क्या संदेह था: नो-रेगेक्स मामले में रिवर्स एक्सरेन्ग दृष्टिकोण का उपयोग करना अनावश्यक है, लेकिन यह ~ 10% प्रदर्शन की कीमत पर कोड को थोड़ा बेहतर बनाता है।

इसके अलावा, मुझे लगता है कि आप जो कर रहे हैं वह एक स्ट्रिंग है और कुछ हद तक एक नंबर जैसा दिखता है। परिणाम अनिश्चित रूप से अन्यथा।

from __future__ import with_statement
from contextlib import contextmanager
import re,time

re_first_num = re.compile(r"\d")
def intcomma_noregex(value):
    end_offset, start_digit, period = len(value),re_first_num.search(value).start(),value.rfind('.')
    if period == -1:
        period=end_offset
    segments,_from_index,leftover = [],0,(period-start_digit) % 3
    for _index in xrange(start_digit+3 if not leftover else start_digit+leftover,period,3):
        segments.append(value[_from_index:_index])
        _from_index=_index
    if not segments:
        return value
    segments.append(value[_from_index:])
    return ','.join(segments)

def intcomma_noregex_reversed(value):
    end_offset, start_digit, period = len(value),re_first_num.search(value).start(),value.rfind('.')
    if period == -1:
        period=end_offset
    _from_index,segments = end_offset,[]
    for _index in xrange(period-3,start_digit,-3):
        segments.append(value[_index:_from_index])
        _from_index=_index
    if not segments:
        return value
    segments.append(value[:_from_index])
    return ','.join(reversed(segments))

re_3digits = re.compile(r'(?<=\d)\d{3}(?!\d)')
def intcomma(value):
    segments,last_endoffset=[],len(value)
    while last_endoffset > 3:
        digit_group = re_3digits.search(value,0,last_endoffset)
        if not digit_group:
            break
        segments.append(value[digit_group.start():last_endoffset])
        last_endoffset=digit_group.start()
    if not segments:
        return value
    if last_endoffset:
        segments.append(value[:last_endoffset])
    return ','.join(reversed(segments))

def intcomma_recurs(value):
    """
    Converts an integer to a string containing commas every three digits.
    For example, 3000 becomes '3,000' and 45000 becomes '45,000'.
    """
    new = re.sub("^(-?\d+)(\d{3})", '\g<1>,\g<2>', str(value))
    if value == new:
        return new
    else:
        return intcomma(new)

@contextmanager
def timed(save_time_func):
    begin=time.time()
    try:
        yield
    finally:
        save_time_func(time.time()-begin)

def testset_xsimple(func):
    func('5')

def testset_simple(func):
    func('567')

def testset_onecomma(func):
    func('567890')

def testset_complex(func):
    func('-1234567.024')

def testset_average(func):
    func('-1234567.024')
    func('567')
    func('5674')

if __name__ == '__main__':
    print 'Test results:'
    for test_data in ('5','567','1234','1234.56','-253892.045'):
        for func in (intcomma,intcomma_noregex,intcomma_noregex_reversed,intcomma_recurs):
            print func.__name__,test_data,func(test_data)
    times=[]
    def overhead(x):
        pass
    for test_run in xrange(1,4):
        for func in (intcomma,intcomma_noregex,intcomma_noregex_reversed,intcomma_recurs,overhead):
            for testset in (testset_xsimple,testset_simple,testset_onecomma,testset_complex,testset_average):
                for x in xrange(1000): # prime the test
                    testset(func)
                with timed(lambda x:times.append(((test_run,func,testset),x))):
                    for x in xrange(50000):
                        testset(func)
    for (test_run,func,testset),_delta in times:
        print test_run,func.__name__,testset.__name__,_delta

और यहाँ परीक्षण के परिणाम हैं:

intcomma 5 5
intcomma_noregex 5 5
intcomma_noregex_reversed 5 5
intcomma_recurs 5 5
intcomma 567 567
intcomma_noregex 567 567
intcomma_noregex_reversed 567 567
intcomma_recurs 567 567
intcomma 1234 1,234
intcomma_noregex 1234 1,234
intcomma_noregex_reversed 1234 1,234
intcomma_recurs 1234 1,234
intcomma 1234.56 1,234.56
intcomma_noregex 1234.56 1,234.56
intcomma_noregex_reversed 1234.56 1,234.56
intcomma_recurs 1234.56 1,234.56
intcomma -253892.045 -253,892.045
intcomma_noregex -253892.045 -253,892.045
intcomma_noregex_reversed -253892.045 -253,892.045
intcomma_recurs -253892.045 -253,892.045
1 intcomma testset_xsimple 0.0410001277924
1 intcomma testset_simple 0.0369999408722
1 intcomma testset_onecomma 0.213000059128
1 intcomma testset_complex 0.296000003815
1 intcomma testset_average 0.503000020981
1 intcomma_noregex testset_xsimple 0.134000062943
1 intcomma_noregex testset_simple 0.134999990463
1 intcomma_noregex testset_onecomma 0.190999984741
1 intcomma_noregex testset_complex 0.209000110626
1 intcomma_noregex testset_average 0.513000011444
1 intcomma_noregex_reversed testset_xsimple 0.124000072479
1 intcomma_noregex_reversed testset_simple 0.12700009346
1 intcomma_noregex_reversed testset_onecomma 0.230000019073
1 intcomma_noregex_reversed testset_complex 0.236999988556
1 intcomma_noregex_reversed testset_average 0.56299996376
1 intcomma_recurs testset_xsimple 0.348000049591
1 intcomma_recurs testset_simple 0.34600019455
1 intcomma_recurs testset_onecomma 0.625
1 intcomma_recurs testset_complex 0.773999929428
1 intcomma_recurs testset_average 1.6890001297
1 overhead testset_xsimple 0.0179998874664
1 overhead testset_simple 0.0190000534058
1 overhead testset_onecomma 0.0190000534058
1 overhead testset_complex 0.0190000534058
1 overhead testset_average 0.0309998989105
2 intcomma testset_xsimple 0.0360000133514
2 intcomma testset_simple 0.0369999408722
2 intcomma testset_onecomma 0.207999944687
2 intcomma testset_complex 0.302000045776
2 intcomma testset_average 0.523000001907
2 intcomma_noregex testset_xsimple 0.139999866486
2 intcomma_noregex testset_simple 0.141000032425
2 intcomma_noregex testset_onecomma 0.203999996185
2 intcomma_noregex testset_complex 0.200999975204
2 intcomma_noregex testset_average 0.523000001907
2 intcomma_noregex_reversed testset_xsimple 0.130000114441
2 intcomma_noregex_reversed testset_simple 0.129999876022
2 intcomma_noregex_reversed testset_onecomma 0.236000061035
2 intcomma_noregex_reversed testset_complex 0.241999864578
2 intcomma_noregex_reversed testset_average 0.582999944687
2 intcomma_recurs testset_xsimple 0.351000070572
2 intcomma_recurs testset_simple 0.352999925613
2 intcomma_recurs testset_onecomma 0.648999929428
2 intcomma_recurs testset_complex 0.808000087738
2 intcomma_recurs testset_average 1.81900000572
2 overhead testset_xsimple 0.0189998149872
2 overhead testset_simple 0.0189998149872
2 overhead testset_onecomma 0.0190000534058
2 overhead testset_complex 0.0179998874664
2 overhead testset_average 0.0299999713898
3 intcomma testset_xsimple 0.0360000133514
3 intcomma testset_simple 0.0360000133514
3 intcomma testset_onecomma 0.210000038147
3 intcomma testset_complex 0.305999994278
3 intcomma testset_average 0.493000030518
3 intcomma_noregex testset_xsimple 0.131999969482
3 intcomma_noregex testset_simple 0.136000156403
3 intcomma_noregex testset_onecomma 0.192999839783
3 intcomma_noregex testset_complex 0.202000141144
3 intcomma_noregex testset_average 0.509999990463
3 intcomma_noregex_reversed testset_xsimple 0.125999927521
3 intcomma_noregex_reversed testset_simple 0.126999855042
3 intcomma_noregex_reversed testset_onecomma 0.235999822617
3 intcomma_noregex_reversed testset_complex 0.243000030518
3 intcomma_noregex_reversed testset_average 0.56200003624
3 intcomma_recurs testset_xsimple 0.337000131607
3 intcomma_recurs testset_simple 0.342000007629
3 intcomma_recurs testset_onecomma 0.609999895096
3 intcomma_recurs testset_complex 0.75
3 intcomma_recurs testset_average 1.68300008774
3 overhead testset_xsimple 0.0189998149872
3 overhead testset_simple 0.018000125885
3 overhead testset_onecomma 0.018000125885
3 overhead testset_complex 0.0179998874664
3 overhead testset_average 0.0299999713898

मैंने सोचा कि डैनियल फ़ोर्टुनोव का एक-रेगेक्स समाधान # 1 होगा और सभी एल्गोरिदम को हरा देगा क्योंकि रेगेक्स सी में परिष्कृत / अनुकूलित और कोडित है, लेकिन नहीं .. मुझे लगता है कि पैटर्न और लुकहेड बहुत महंगे हैं। यह ऊपर के इंक्वामा के समय में लगभग दोगुना हो जाता है, यहां तक ​​कि रेगेक्स को पहले से तैयार करने के साथ।
समानता ३

0

यह पीईपी प्रति अजगर में पकाया जाता है -> https://www.python.org/dev/peps/pep-0378/

हजारों विभाजक के साथ पूर्णांक दिखाने के लिए बस प्रारूप (1000, ', d') का उपयोग करें

पीईपी में वर्णित अधिक प्रारूप हैं, इस पर हैं


-1

एक अन्य प्रकार्य है जो एक जनरेटर फ़ंक्शन का उपयोग करता है जो पूर्णांकों के लिए काम करता है:

def ncomma(num):
    def _helper(num):
        # assert isinstance(numstr, basestring)
        numstr = '%d' % num
        for ii, digit in enumerate(reversed(numstr)):
            if ii and ii % 3 == 0 and digit.isdigit():
                yield ','
            yield digit

    return ''.join(reversed([n for n in _helper(num)]))

और यहाँ एक परीक्षण है:

>>> for i in (0, 99, 999, 9999, 999999, 1000000, -1, -111, -1111, -111111, -1000000):
...     print i, ncomma(i)
... 
0 0
99 99
999 999
9999 9,999
999999 999,999
1000000 1,000,000
-1 -1
-111 -111
-1111 -1,111
-111111 -111,111
-1000000 -1,000,000

-1

बस उपवर्ग long(या float, या जो भी)। यह अत्यधिक व्यावहारिक है, क्योंकि इस तरह आप अभी भी गणित ऑप्स (और इसलिए मौजूदा कोड) में अपने नंबरों का उपयोग कर सकते हैं, लेकिन वे सभी आपके टर्मिनल में अच्छी तरह से प्रिंट करेंगे।

>>> class number(long):

        def __init__(self, value):
            self = value

        def __repr__(self):
            s = str(self)
            l = [x for x in s if x in '1234567890']
            for x in reversed(range(len(s)-1)[::3]):
                l.insert(-x, ',')
            l = ''.join(l[1:])
            return ('-'+l if self < 0 else l) 

>>> number(-100000)
-100,000
>>> number(-100)
-100
>>> number(-12345)
-12,345
>>> number(928374)
928,374
>>> 345

8
मुझे उपवर्ग विचार पसंद है, लेकिन क्या __repr__()ओवरराइड करने की सही विधि है? मैं ओवरराइड करने __str__()और __repr__()अकेला छोड़ने का सुझाव दूंगा , क्योंकि int(repr(number(928374)))काम करना चाहिए, लेकिन int()अल्पविराम पर घुट जाएगा।
चरणवचन

@steveha के पास एक अच्छा बिंदु है, लेकिन औचित्य होना चाहिए था कि number(repr(number(928374)))काम नहीं करता है, नहीं int(repr(number(928374)))। सभी समान, इस दृष्टिकोण को सीधे काम करने के लिए print, जैसा कि ओपी ने अनुरोध किया, __str__()विधि को इसके बजाय ओवरराइड किया जाना चाहिए __repr__()। बावजूद, कोर कॉमा सम्मिलन तर्क में एक बग प्रतीत होता है।
मार्टीन्यू


-8

तैरने वालों के लिए:

float(filter(lambda x: x!=',', '1,234.52'))
# returns 1234.52

Ints के लिए:

int(filter(lambda x: x!=',', '1,234'))
# returns 1234

5
जो अल्पविराम को दूर करता है। काम करते हुए, ओपी ने उन्हें जोड़ने का तरीका पूछा । इसके अलावा, कुछ float('1,234.52'.translate(None, ','))और अधिक सरल और संभवतः तेज हो सकता है।
अगली सूचना तक रोक दिया गया।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.