python从id的日期范围中查找唯一的日期

时间:2016-11-25 19:47:20

标签: python date

我有问题,我无法通过4天。我是python noobie。 我正在使用python 2.6编写unix box ...并且没有像numpy,pandas那样的额外liberales。

我需要做的是尽量减少下面文件的行数。因此,当相同id1的日期范围中的日期,id2相互覆盖时,它们需要被覆盖。但正如你所看到的那样,期望输出具有最小值和最大值是不够的,因为有些日期不是日复一日。

输入

array(
    array(
        'achievements.levelup.desc',
        'You unlocked the Achievement'
    ),
    array(
        'achievements.levelup.ok',
        'OK'
    ),
    array(
        'achievements.levelup.reward'
        'Reward: <b><font size="30" color="#7adde9">%amount%</font></b> %currency_name%'
    )
)

预期产出

ID1|IDTYPE2|20160802|20160912|
ID1|IDTYPE2|20160803|20160913|
ID1|IDTYPE2|20160804|20160914|
ID1|IDTYPE2|20160805|20160915| 
ID1|IDTYPE2|20160808|20160916|
ID1|IDTYPE2|20160925|20160925|
ID2|IDTYPE2|20160925|20160925|

我尝试了什么,但它让我得到了很多结果

ID1|IDTYPE2|20160802|20160916|
ID1|IDTYPE2|20160925|20160925|
ID2|IDTYPE2|20160925|20160925|

2 个答案:

答案 0 :(得分:1)

假设输入文件ID和日期始终按递增顺序排列。下面的代码应该有效。

当ID改变或当前行date1&gt;时,

tmpline充当缓冲保持行以附加到输出。 tmpline缓冲区中的date2(意味着我们需要开始一个新的日期范围)。如果发现当前行中的date2大于缓冲区中的date2,则缓冲列2(date2)将被覆盖。

output = []
with open(filename, 'rU') as f:
    prev_id = None
    tmpline = ''
    for line in f:
        line = line.strip()
        (id, date1, date2, dummy) = line.rsplit('|', 3)
        # line = 'ID1|IDTYPE2|20160802|20160912|'
        # id = 'ID1|IDTYPE2'
        # date1 = '20160802'
        # date2 = '20160912'
        # dummy = ''

        # append to output when new ID changes or 
        # date1 > previous date2 (start new range of dates)
        if prev_id != id or date1 > tmpline[2]:
            if tmpline:
               output.append('|'.join(tmpline))
            tmpline = [id, date1, date2, dummy]

        # override end date if larger
        elif date2 > tmpline[2]:
            tmpline[2] = date2
        prev_id = id

    # take care last line
    tmpline = '|'.join(tmpline)
    if tmpline != output[-1]:
        output.append(tmpline)

输出包含行列表,打印到控制台或可以写入另一个文件

# print out the ouput
for line in output:
    print line


# based on the input from the post
# output = ['ID1|IDTYPE2|20160802|20160916|', 'ID1|IDTYPE2|20160925|20160925|', 'ID2|IDTYPE2|20160925|20160925|']

答案 1 :(得分:0)

您使用的日期格式的一个很酷的事情是您甚至不必将其转换为除字符串以外的任何内容。

它使它变得更容易,因为你可以简单地说date1 > date2并且字符串比较适用于它们!

说过你可以这样做:

f = open(filename, 'rU')
ranges = {}
for line in f:
    elem = line.split("|") # get every item of the row in a list

    if elem[0] not in ranges: 
        ranges[elem[0]] = []

    matched = False
    for x in ranges[elem[0]]: # check the current line overlap with any previous ones
        if elem[2] >= x[1] and elem[2] <= x[2] or \
           elem[3] >= x[1] and elem[3] <= x[2] or \
           elem[2] <= x[1] and elem[3] >= x[2] or \
           elem[2] >= x[1] and elem[3] <= x[2]:
            x[1] = min(elem[2], x[1]) # modify the date range 
            x[2] = min(elem[3], x[2]) 
            matched = True
            break

    if not matched: # if it does not overlap add it.
        ranges[elem[0]].append([elem[1], elem[2], elem[3]])

# This is just for display purposes 
for key in ranges.iterkeys():
    for v in ranges[key]:
        print key + '|' + v[0] + '|' + v[1] + '|' + v[2] + '|'

您可能需要考虑的是您是否需要按特定顺序排列的行,如果这样做,您将需要使用字典以外的其他内容来存储范围。