2016-11-25 13 views
2

私は4日間は行けないという問題があります。私はpython noobieです。 私はPython 2.6でunixボックスに取り組んでいます...そして、numpy、pandasのような追加のリベラルはありません。python idの日付範囲からユニークな日付を検索

私がする必要があるのは、できるだけ下のファイルの行数を少なくすることです。したがって、同じid1、id2の日付範囲の日付が互いにカバーしている場合は、それらをオーバーライドする必要があります。しかし、あなたが出力を期待して見ることができるように、それらの最小値と最大値は十分ではありません。なぜなら、日付のいくつかは毎日ではないからです。

入力

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| 

が、それは多くの結果

f = open(filename, 'rU') 
outf = open(filename + '_date_diff', 'w') 
dict_of_ID_dates = defaultdict(list) 
for line in f: 
    columns = line.split("|") 
    ID1 = (columns[0]) 
    IDType2 = (columns[1]) 
    start = (columns[2]) 
    end = (columns[3]) 
    start_date = datetime.datetime.strptime(start,'%Y%m%d').date() 
    end_date = datetime.datetime.strptime(end,'%Y%m%d').date() 
    diff = end_date - start_date 
    list_of_dates =[] 
    date_ranges = range(diff.days +1) 
    # [0,1,2,3] 
    for date in date_ranges: 
    dates = (start_date + datetime.timedelta(date)).isoformat() 
# [datetime format dates = '20160101'] 
    if dates not in dict_of_ID_dates.values(): 
     dict_of_ID_dates[ID].append(dates) 
print (dict_of_ID_dates) 
+0

ファイルに書き込むことができます彼らはすでにsprited、フォームを提示するafregadedされている場合、行の18 milionsのような巨大でプリントアウト、行のリストが含まれています。そして私はどこにいたのですか? –

答えて

1

は、入力ファイルIDと日付が常に増加する順番であると仮定します。以下のコードは動作するはずです。

tmplineは、IDが変更されたときに出力されるバッファ保持行またはtmplineバッファの現在の行date1> date2(新しい日付範囲を開始する必要があることを意味します)として機能します。現在の行のdate2がbufferの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|'] 
+0

こんにちはスカイ:)あなたのソリューションは、私が求めていたように機能します。しかし、私が@Rodolfoについて上記で説明したように、私は家でそれを確認することしかできませんでした。私は明日の仕事でそれを試して、ロドルフォの賞賛の下で更新を残しました。良い週末を! –

+0

あとでお知らせください。私のコードはPython 2と3の両方で動作するはずです。最後の行INPUT ID1の – Skycc

+0

他の部分を世話をするためにいくつかのコードを編集した| IDTYPE2 | 20141208 | 20160606 ID1 | IDTYPE2 | 20141209 | 20160607 ID1 | IDTYPE2 | 20141210 | 20160608 ID1 | IDTYPE2 | 20141211 | 20160609 ID1 | IDTYPE2 | 20141212 | 20160610 ID1 | IDTYPE2 | 20141215 | 20160613 ID1 | IDTYPE2 | 20160603 | 20160603 ID1 | IDTYPE2 | 20160610 | 20160610 ID1 | IDTYPE2 | 20160617 | 20160617 ID1 | IDTYPE2 | 20160624 | 20160624 ID1 | IDTYPE2 | 20160701 | 20160701 コード出力 AAVL | SHSO | 20141208 | 20160606 AAVL | SHSO | 20160701 | 20160701 期待される出力 ID1 | IDTYPE2 | 20141208 | 20160613 ID1 | IDTYPE2 | 20160617 | 20160617 ID1 | IDTYPE2 | 20160624 | 20160624 ID1 | IDTYPE2 | 20160701 | 20160701 –

0

あなたは日付の書式についてのクールなことに私をgavesあなたは文字列以外のものに変換する必要さえないということを使用しています。

単純に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] + '|' 

あなたがが検討する必要があります何かがあなたが特定の順序で行を必要とするかどうかで、あなたが行う場合は、以外のものを使用する必要があります範囲を格納する辞書。

+0

ところで、私はPython 2.6でそれをテストすることができませんでした。 – Rodolfo

+1

こんにちはRodolfo :)私はそれほどひどく、日付の範囲を比較する解決策に私の心をロックしている、私は助けなしにそれを通過しないだろう:)あなたのソリューションは私が求めていたように動作します。ありがとう!残念ながら私は自宅でしかチェックすることができませんでした。私は仕事で使うよりもPythonのバージョンを持っています。私は月曜日にそれを確認し、それがどうなるか、あなたに知らせるでしょう。もう一度ありがとう! –