0

リストのリストがあり、各リストには 4 つの要素が含まれており、要素は、、、、をid表します。そのリストのとの 値が常に前のリストに表示された最新の値に依存するように、各リストを操作しています。リストの以前のリストは、年齢差が より小さくないリストです。リストのリストは、年齢順にソートされています。ageval1val2val1val2timeDelta

私のコードは完璧に動作していますが、遅いです。* *とマークされた行は、あまりにも多くのリストのリストを生成しているように感じますが、リストを最初から削除し続けることで回避できると思います。次のリストとの年齢差がtimeDelta.

myList = [
          [1,   20, '',     'x'],
          [1,   25, 's',    ''],
          [1,   26, '',     'e'],
          [1,   30, 'd',    's'],
          [1,   50, 'd',    'd'],
          [1,   52, 'f',    'g']
          ]


age_Idx =1
timeDelta = 10

for i in range(len(myList))[1:]:
    newList = myList[:i+1] #Subset of lists.  #********
    respList = newList.pop(-1) 
    currage = float(respList[age_Idx])
    retval = collapseListTogether(newList, age_Idx, currage, timeDelta)
    if(len(retval) == 0):
        continue
    retval[0:2] = respList[0:2]
    print(retval)

def collapseListTogether(li, age_Idx, currage, timeDelta):
    finalList = []
    for xl in reversed(li) :
        #print(xl)
        oldage = float(xl[age_Idx])
        if ((currage-timeDelta) <= oldage < currage):
            finalList.append(xl)
        else:
            break
    return([reduce(lambda a, b: b or a, tup) for tup in zip(*finalList[::-1])])

[1, 20, '',     'x'] ==> Not dependent on anything. Skip this list
[1, 25, 's',    '']    == > [1, 25, '', 'x'] 
[1, 26, '',     'e']   ==>  [1, 26, 's', 'x']
[1, 30, 'd',    's']   ==>  [1, 30, 's', 'e']
[1, 50, 'd',    'd']   ==>  Age difference (50-30 = 20) which is more than 10 
[1, 52, 'f',    'g']   ==>  [1, 52, 'd', 'd']
4

2 に答える 2

0

あなたの例が正しいと仮定すると、年齢でソートされているため、1回のパスでこれを実行できない理由はわかりません。検査した最後のサブリストの違いが大きすぎる場合は、以前は何もカウントされないことがわかっているため、現在のサブリストを変更せずにそのままにしておく必要があります。

previous_age = None
previous_val1 = ''
previous_val2 = ''

for sublist in myList:
    age = sublist[1]
    latest_val1 = sublist[2]
    latest_val2 = sublist[3]
    if previous_age is not None and ((age - previous_age) <= timeDelta):
        # there is at least one previous list            
        sublist[2] = previous_val1
        sublist[3] = previous_val2
    previous_age = age
    previous_val1 = latest_val1 or previous_val1
    previous_val2 = latest_val2 or previous_val2

テスト時に、そのコードは、最初の myList に対して次の変更された値を生成します。

[[1, 20, '', 'x'],
 [1, 25, '', 'x'],
 [1, 26, 's', 'x'],
 [1, 30, 's', 'e'],
 [1, 50, 'd', 'd'],
 [1, 52, 'd', 'd']]

リストをその場で編集するのではなく、新しいリストを作成するか、スキップされた行をそのままにしておくのではなく、完全に省略するのは簡単な変更です。

reduce と list の内包表記は強力なツールですが、すべての問題に適しているわけではありません。

于 2013-08-14T20:50:05.760 に答える
0

私はちょうどあなたのデータ構造とあなたのコードを書き直しています:

from collections import namedtuple
Record = namedtuple('Record', ['id', 'age', 'val1', 'val2'])
myList = [
      Record._make([1,   20, '',     'x']),
      Record._make([1,   25, 's',    '']),
      Record._make([1,   26, '',     'e']),
      Record._make([1,   30, 'd',    's']),
      Record._make([1,   50, 'd',    'd']),
      Record._make([1,   52, 'f',    'g'])
]

timeDelta = 10

for i in range(1, len(myList)):
    subList = list(myList[:i+1])
    rec = supList.pop(-1) 
    age = float(rec.age)
    retval = collapseListTogether(subList, age, timeDelta)
    if len(retval) == 0:
        continue
    retval.id, retval.age = rec.id, rec.age
    print(retval)

def collapseListTogether(lst, age, tdelta):
    finalLst = []
    [finalLst.append(ele) if age - float(ele.age) <= tdelta and age > float(ele.age)
     else None for ele in lst]
    return([reduce(lambda a, b: b or a, tup) for tup in zip(*finalLst[::-1])])

あなたのコードは私には読めません。ロジックは変更していませんが、パフォーマンスのために場所を変更しただけです。

解決策の 1 つは、4 要素のリストを tuple に置き換えることです。Python で有名な高性能コンテナーである namedtuple を使用するとさらに効果的です。また、解釈された言語では for ループを避ける必要があります。Python では、可能であれば for ループの代わりに内包表記を使用してパフォーマンスを向上させます。あなたのリストはそれほど大きくないので、効率的な行解釈で得られる時間は、改行で得られる時間よりも長くなるはずです。

私には、あなたのコードは機能しないはずですが、よくわかりません。

于 2013-08-14T20:42:36.830 に答える