0

一連の数値を指定して、完全な「数値範囲」セットを作成する必要があります。次のようなリストから始めます。

ID   START  
*    0  
a    4  
b    70  
c    700  
d    701  
e    85  
  • ここで、「def」はデフォルトの範囲であり、ギャップを「埋める」必要があります
  • 「重複」は開始データの値 (70、700、701) です。

そして、次の結果が必要です。

ID  START  END  
*     0 - 39  
a     4 - 49  
*     5 - 69  
c   700 - 7009  
d   701 - 7019  
b   702 - 709  
*    71 - 849  
e    85 - 859  
*    86 - 9  

私が理解しようとしているのは、これに取り組むための何らかのアルゴリズムまたは設計パターンがあるかどうかです。いくつかアイデアはありますが、最初は「専門家」に任せようと思いました。私はPythonを使用しています。

どんなアイデアや方向性も大歓迎です。私が持っているいくつかの最初のアイデア:

  • 開始値と終了値が完全にパディングされた「範囲」リストを作成します。したがって、デフォルトは 0000 から 9999 になります
  • その場で作成される「分割」リストを作成する
  • 各値を分割リストの値と比較する「範囲」リストをループします。
  • 重複が見つかった場合は、分割リストの値を削除し、新しい範囲を追加します。
4

1 に答える 1

0
import operator

ranges = {
    '4'  : 'a',
    '70' : 'b',
    '700': 'c',
    '701': 'd',
    '85' : 'e',
    '87' : 'a',
}

def id_for_value(value):
    possible = '*'
    for idvalue, id in sorted(ranges.iteritems()):
        if value.startswith(idvalue):
            possible = id
        elif idvalue > value:
            break
    return possible

特定の値の ID を知るにはこれで十分です。テスト:

assert id_for_value('10') == '*'
assert id_for_value('499') == 'a'
assert id_for_value('703') == 'b'
assert id_for_value('7007') == 'c'
assert id_for_value('7017') == 'd'
assert id_for_value('76') == id_for_value('83') == '*'
assert id_for_value('857') == 'e'
assert id_for_value('8716') == 'a'

本当に範囲が必要な場合は、 itertools.groupby を使用して計算できます。

def firstlast(iterator):
    """ Returns the first and last value of an iterator"""
    first = last = iterator.next()
    for value in iterator:
        last = value
    return first, last

maxlen = max(len(x) for x in ranges) + 1
test_range = ('%0*d' % (maxlen, i) for i in xrange(10 ** maxlen))
result = dict((firstlast(gr), id) 
              for id, gr in itertools.groupby(test_range, key=id_for_value))

与えます:

{('0000', '3999'): '*',
 ('4000', '4999'): 'a',
 ('5000', '6999'): '*',
 ('7000', '7009'): 'c',
 ('7010', '7019'): 'd',
 ('7020', '7099'): 'b',
 ('7100', '8499'): '*',
 ('8500', '8599'): 'e',
 ('8600', '8699'): '*',
 ('8700', '8799'): 'a',
 ('8800', '9999'): '*'}
于 2009-02-19T19:05:03.313 に答える