2010-11-02 9 views
5

में संख्याओं की सूची से स्वरूपित संख्यात्मक रेंज स्ट्रिंग को प्रिंट करना मैंने चरण वर्ग को अनुक्रमित करने के लिए संख्या सूचियों को संकुचित और विस्तारित करने के लिए लिखा है, चरण चरण समेत चरण मान 1 से अधिक है। कोड अभी भी घबराहट महसूस करता है। क्या ऐसे पुस्तकालय हैं जो ऐसा कुछ कर सकते हैं? संभवतः सरल कोड?पायथन

import re 

class Foo(object): 

    def __init__(self, num_list): 
     self.num_list = sorted(list(set([ int(n) for n in num_list ]))) 
    # end def __init__ 

    def gen_seq_data(self): 
     self.seq_data  = list() 
     index_offset  = None 
     backward_step_value = None 
     forward_step_value = None 
     sub_list   = list() 
     sub_list_step_value = None 
     for index, num in enumerate(self.num_list): 

      if index - 1 < 0: 
       backward_step_value = None 
      # end if 
      else: 
       backward_step_value = num - self.num_list[ index - 1 ] 
      # end else 

      try: 
       forward_step_value = self.num_list[ index + 1 ] - num 
      # end try 
      except IndexError: 
       forward_step_value = None 
      # end except 

      if backward_step_value is None: 
       sub_list.append(num) 
      # end if 
      elif backward_step_value == forward_step_value: 
       sub_list.append(num) 
       if forward_step_value is None: 
        self.seq_data.append((sub_list_step_value, sub_list)) 
       # end if 
      # end if 
      elif backward_step_value == sub_list_step_value: 
       sub_list.append(num) 
       if sub_list: 
        self.seq_data.append((sub_list_step_value, sub_list)) 
       # end if 
       sub_list = list() 
      # end elif 
      else: 
       if sub_list: 
        self.seq_data.append((sub_list_step_value, sub_list)) 
       # end if 
       sub_list = [ num ] 
       if forward_step_value is None: 
        self.seq_data.append((sub_list_step_value, sub_list)) 
       # end if 
      # end else 

      try: 
       sub_list_step_value = sub_list[ -1 ] - sub_list[ -2 ] 
      # end try 
      except IndexError: 
       sub_list_step_value = None 
      # end except 
     # end for 
    # end def gen_seq_object 

    def format_elements(self): 
     format_elements = list() 
     for step, num_list in self.seq_data: 
      if step is None: 
       format_elements.append('%s' % (num_list[ 0 ])) 
      # end if 
      elif step == 1: 
       format_elements.append('%s-%s' % (num_list[ 0 ], num_list[ -1 ])) 
      # end elif 
      else: 
       format_elements.append('%s-%sx%s' % (num_list[ 0 ], num_list[ -1 ], step)) 
      # end else 
     # end for 
     return format_elements 
    # end def format_range 

    def format_range(self): 
     return ','.join(self.format_elements()) 
    # end def format_range 

    def expand_range(self): 
     num_list = list() 
     for r_token in self.format_range().split(','): 
      if r_token.isdigit(): 
       num_list.append(int(r_token)) 
      # end if 
      elif '-' in r_token: 
       if 'x' in r_token: 
        start, end, step = re.split(r'[-|x]', r_token) 
        num_list.extend(range(int(start), int(end) + 1, int(step))) 
       # end if 
       else: 
        start, end = r_token.split('-') 
        num_list.extend(range(int(start), int(end) + 1)) 
       # end else 
      # end elif 
     # end for 
     return num_list 
    # end def expand_range 

# end class Foo 

इनपुट/आउटपुट:

data = [ 1, 4, 5, 6, 10, 15, 16, 17, 18, 20, 22, 24, 26, 27, 28, 30, 35, 40, 45, 50, 56, 63, 66, 69, 72 ] 

foo = Foo(data) 
foo.gen_seq_data() 

print data 

print foo.format_range() 
1,4-6,10,15-18,20-26x2,27,28,30-50x5,56,63-72x3 

print foo.expand_range() 
[1, 4, 5, 6, 10, 15, 16, 17, 18, 20, 22, 24, 26, 27, 28, 30, 35, 40, 45, 50, 56, 63, 66, 69, 72] 
+0

कृपया अपना ठीक करें खरोज। आपका कोड गलत तरीके से स्वरूपित है। कृपया (1) प्रश्न संपादित करें, (2) पृष्ठ के दाईं ओर स्वरूपण निर्देश पढ़ें और (3) आपके पास मौजूद कोड के प्रत्येक टुकड़े को पोस्ट करने से बचें। आपके पास ** समस्या ** क्या है? कोड का सबसे छोटा टुकड़ा क्या है जो यह ** समस्या ** दिखाता है? –

+3

@ user494203: "# end if" आदि लाइनों को फेंक दें; वे राक्षसी रूप से बेकार हैं, खासकर वे जो 'एलिफ' और 'else' से पहले होते हैं। यदि आप ऐसा करते हैं, तो लोग आपके कोड को पढ़ने और आगे के अनधिकृत सुझाव देने के इच्छुक हो सकते हैं। –

उत्तर

2

एक। सभी #END टिप्पणियां हटाएं। वे भयानक बेकार हैं। आपका इंडेंटेशन खुद के लिए बोलता है। इसका इस्तेमाल करें।

दो। इसे एक वर्ग मत बनाओ। यह अलग जिम्मेदारियों के साथ एक विशिष्ट वस्तु नहीं है। यह सिर्फ एक एल्गोरिदम है। कार्यों से बना है। सबसे अच्छा यह सभी स्थैतिक तरीकों के साथ एक वर्ग है।

तीन। ऐसा कभी न करें

for index, num in enumerate(self.num_list): 
     if index - 1 < 0: 
      backward_step_value = None 
     # end if 
     else: 
      backward_step_value = num - self.num_list[ index - 1 ] 
     # end else 

यदि पहला तत्व विशेष है, तो इसे अलग से इलाज करें।

backward_step_value = self.num_list[0] 
for num in self.num_list[1:]: 

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

अंत में, यह एक "कमी" है। जेनरेटर फ़ंक्शन

def reduce_list(some_list): 
    v= min(some_list) 
    low, high = v, v 
    for v in sorted(some_list)[1:]: 
     if v == high+1: 
      high= high+1 
     else: 
      yield low, high 
    yield low, high 

जो आपकी समेकित श्रेणियों की सूची उत्पन्न कर सकता है। फिर आप उन्हें प्रारूपित कर सकते हैं।

format_elements(reduce_list(some_list)) 
+0

यह समाधान ओपी के समाधान का सबसे कठिन हिस्सा प्राप्त नहीं करता है, अर्थात् केवल निरंतर श्रेणियों की पहचान नहीं करता है, लेकिन एक निश्चित चरण के साथ है> 1. – jchl

+0

@jchl: सही। बिंदु उनके कोड को ठीक नहीं करना था। बिंदु कम "गुंजाइश" होने के लिए कोड को संशोधित करने का एक तरीका प्रदान करना था। '1' के बजाय एक चर के रूप में चरण को शामिल करने के लिए इसे विस्तार के रूप में करना मुश्किल नहीं होना चाहिए। –

1

निम्नलिखित समाधान गैर-निरंतर पर्वतमाला संभालती है, और यह भी लंबाई की सीमाओं की अनदेखी के व्यवहार को बरकरार रखता है 2.

def reduce_list(seq): 
    l = sorted(set(seq)) 
    low = high = l[0] 
    step = None 
    for v in l[1:]: 
     if step is None or v - high == step: 
      # Extend the current range. 
      step = v - high 
      high = v 
     elif high - low == step: 
      # The current range only has two values. Yield the 
      # first value, and start a new range comprising the 
      # second value and the current value. 
      yield low, low, None 
      step = v - high 
      low = high 
      high = v 
     else: 
      # Yield the current range, and start a new one. 
      yield low, high, step 
      low = high = v 
      step = None 
    if high - low == step: 
     # The final range has only two values. Yield them 
     # individually. 
     yield low, low, None 
     step = None 
     low = high 
    yield low, high, step 

def format_element(low, high, step): 
    if step is None: 
     assert low == high 
     return "%s" % (low,) 
    elif step == 1: 
     return "%s-%s" % (low, high) 
    else: 
     return "%s-%sx%s" % (low, high, step) 

def format_list(seq): 
    return ','.join(format_element(*e) for e in seq) 

यहाँ कुछ परीक्षण कोड है:

def test(*args): 
    print args, "==", format_list(reduce_list(args)) 

test(1) 
test(1, 2) 
test(1, 2, 3) 
test(0, 10) 
test(0, 10, 20) 
test(0, 10, 11, 12, 14, 16) 
test(0, 2, 4, 8, 16, 32, 64) 
test(0, 1, 3, 4, 6, 7, 9, 10) 
test(0, 1, 3, 6, 10, 15, 21, 28) 

जो आउटपुट:

(1,) == 1 
(1, 2) == 1,2 
(1, 2, 3) == 1-3 
(0, 10) == 0,10 
(0, 10, 20) == 0-20x10 
(0, 10, 11, 12, 14, 16) == 0,10-12,14,16 
(0, 2, 4, 8, 16, 32, 64) == 0-4x2,8,16,32,64 
(0, 1, 3, 4, 6, 7, 9, 10) == 0,1,3,4,6,7,9,10 
(0, 1, 3, 6, 10, 15, 21, 28) == 0,1,3,6,10,15,21,28 
+0

आपकी मदद के लिए धन्यवाद। ये महान समाधान हैं। – Bip