2012-01-10 8 views
1

my previous questionの後に、2009年の最初の非2009年のAB2オブジェクト(subAB)のリストに2つのファイルAとBを読み込みますそれの前に行。Pythonは日付時刻を比較して再帰的に2つのオブジェクトリストを結合します

file A: 20111225, 20111226, 20090101 
file B: 20111225, 20111226, 20090101, 20090102, 20111227, 20090105 

が生じるはずである:例えば

class AB2(object): 
    def __init__(self, datetime, a=False, b=False): 
     self.datetime = datetime 
     self.a = a 
     self.b = b 
     self.subAB = [] 

(角括弧がsubABリストを表示するには)

AB2(20111225, a = true, b = true, []) 
AB2(20111226, a = true, b = true, 
    [AB2(20090101, a = true, b = true, []), 
    AB2(20090102, a = false, b = true, [])], 
AB2(20111227, a = false, b = true, 
    [AB2(20090105, a = false, b = true)]) 

残念ながら、これは以前のソリューションを複雑に:

list_of_objects = [(i, i in A, i in B) for i in set(A) | set(B)] 

ので:オーダーが重要である

  • (2009の項目がファイルにする前に、まず2011項目に入る)

  • は、ファイル内の同じ日時の複数の項目が存在することができ

  • subABオブジェクトのリストで今興味も

これらの理由により、setが現在存在しているため、setを使用することはできません(重複を削除して順序を失うため)。私はOrderedSet recipeを使って調査しましたが、ここでそれを適用する方法は考えられません。

私の現在のコード:

listA = open_and_parse(file A) # list of parsed dates 
listAObjects = [AB2(dt, True, None) for dt in listA] # list of AB2 Objects from list A 
nested_listAObjects = nest(listAObjects) # puts 2009 objects into 2011 ones 
<same for file B> 
return combine(nested_listAObjects, nested_listBObjects) 

巣の方法:(。前の2011項目に2009個のアイテムを置く無視2009個のアイテムを、彼らは、ファイルの先頭にいる場合)

def nest(list): 
    previous = None 
    for item in list:  
     if item.datetime.year <= 2009: 
      if previous is not None: 
       previous.subAB.append(item) 
      else: 
       previous = item 

    return [item for item in list if item.datetime.year > 2009] 

しかし、私はちょっと私のcombine機能につかまっています:

この時点で、魔法なし、combinedは次のようになります。

AB2(20111225, a = true, b = None, []) # \ 
AB2(20111225, a = None, b = true, []) #/these two should merge to AB2(20111225, a = true, b = true, []) 
AB2(20111226, a = true, b = None, 
    [AB2(20090101, a = true, b = None, []), 
    AB2(20090102, a = true, b = None, [])], 
AB2(20111226, a = None, b = true, 
    [AB2(20090101, a = None, b = true, [])], 
# The above two lines should combine, and so should their subAB lists (but only recurse to that level, not infinitely) 
AB2(20111227, a = None, b = true, 
    [AB2(20090105, a = None, b = true)]) 

を私は私が新しい質問を投稿することが大丈夫だ願っています - それは私の前のものと完全に異なる解決策になるでしょう。また、長いポストには申し訳ありませんが、私はあなたが問題を完全に理解できるように、そしておそらくcombineメソッドだけでなく、問題全体を解決する代替ソリューションを提供するために、私がやっていることをすべて説明する方が良いと思っていました。ありがとう!


編集:明確化:

は基本的に、私は2台の接続されたコンピュータからのログをチェックし、それらの両方が特定の時間にシャットダウン、またはちょうど1か比較しています。実際の2012年の時間を取得する前にリセットされた場合、コンピュータは2009年に起動します(ただし、必ずしも1月1日 - 1月4日などではありません)。したがって、2009年のシャットダウンを前回のシャットダウンと関連づけようとしています。そのため、シャットダウンが速やかに再開することがわかります。

2011年/ 2012年の日付にする必要がありますが、2009年はソートしないでください。 1台のコンピュータのログファイル(私の例ではfileA)は、次のようになります。

現実に
2011/12/15 
2011/12/17 
2011/12/19 # Something goes wrong, and causes the computer to reset 5 times rapidly 
2009/01/01 
2009/01/01 
2009/01/04 
2009/01/01 
2011/12/20 # And everything is better again 
2011/12/25 

、彼らは実際に日付時刻(例えば2009/01/01 01:57:01)しているので、2つの日付時刻が一定の範囲内にある場合、私は単純に比較することができますtimedelta

私はクリーナー全体的な解決策/アプローチ、またはAB2オブジェクトのこれらの2つのリストの組み合わせの問題の特定の解決策の後です。

2つを組み合わせる最も簡単な方法は、ソートされた結合リスト(2009年のオブジェクトがすでに親に置かれている)を繰り返し、次のアイテムが現在のものと同じ日付であるかどうかを比較し、これらのアイテム。

+0

あなたはAとBのファイルがソートされていないから日付を一致させたいが、すべての非2009年の日付が昇順で発生したどのようにそれは私には明確ではないでしょうか? 2009年以外の日付が複数存在することはありますか? –

+0

*新しい質問を投稿するのは大丈夫です。* - 新しい質問が投稿されたら、新しい質問を投稿するのはまさに正しいことです。 – MattH

+0

@JanneKarila申し訳ありませんが明確ではなかった、私は明確にするために編集します。 –

答えて

0

これは比較でややこしいことですが、これを行うにはもっとクリーンな方法がありますが、これはうまくいくと思われ、比較的効率的でなければなりません。

私は、日付の順序が重要であると仮定しています。増加する日付は2つの入力ストリームから比較され、結合されます。前の日付が発生すると、それらは収集され、結合され、前のより大きな日付に追加されます。

簡潔にするため、この例ではAB2クラスのインスタンスの代わりにタプルを作成しました。

from cStringIO import StringIO 
fileA = StringIO("""20111225, 20111226, 20090101""") 
fileB = StringIO("""20111225, 20111226, 20090101, 20090102, 20111227, 20090105""") 

def fileReader(infile): 
    for line in infile: 
    for part in line.split(','): 
     yield part.strip() 

def next_or_none(iterable): 
    for value in iterable: 
    yield value 
    yield None 

def combine(a,b): 
    current_val = None 
    hasA = hasB = False 
    next_a, next_b = next_or_none(a).next, next_or_none(b).next 
    current_a, current_b = next_a(), next_b() 
    while True: 
    if current_val is None: 
     if current_a == current_b: 
     current_val = current_a 
     hasA = hasB = True 
     current_a, current_b = next_a(), next_b() 
     elif current_a is not None and (current_b is None or current_a < current_b): 
     current_val = current_a 
     hasA = True 
     current_a = next_a() 
     elif current_b is not None and (current_a is None or current_b < current_a): 
     current_val = current_b 
     hasB = True 
     current_b = next_b() 
     else: 
     break 
    else: # There's a current_val 
     sub_a = [] 
     while current_a is not None and current_a < current_val: 
     sub_a.append(current_a) 
     current_a = next_a() 
     sub_b = [] 
     while current_b is not None and current_b < current_val: 
     sub_b.append(current_b) 
     current_b = next_b() 
     if sub_a or sub_b: 
     sub_ab = list(combine(sub_a,sub_b)) 
     else: 
     sub_ab = [] 
     yield (current_val,hasA,hasB,sub_ab) 
     current_val = None 
     hasA = hasB = False 

for row in combine(fileReader(fileA),fileReader(fileB)): 
    print row 

収量:

('20111225', True, True, []) 
('20111226', True, True, [('20090101', True, True, []), ('20090102', False, True, [])]) 
('20111227', False, True, [('20090105', False, True, [])]) 
+0

これはとても面白いですね、ありがとう!私は今夜​​それを完全に理解する少しのトラブルを抱えているが、私は明日の朝にそれに亀裂を与えて、どうやって行くのか見てみよう:) –

関連する問題