我有一个列表列表,每个列表包含四个元素,元素代表id
,age
,val1
,val2
。我正在操纵每个列表,使得该列表的val1
和val2
值始终取决于先前列表中看到的最新值。列表的先前列表是年龄差异不小于timeDelta
的列表。列表列表按年龄排序。
我的代码工作正常,但速度很慢。我觉得标记 * * 的行生成了太多的列表列表并且可以避免,通过继续从开头删除列表我知道年龄差异列表的下一个列表超过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']
答案 0 :(得分: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])])
我的代码不可读。我没有更改逻辑,只是修改了性能的位置。
其中一条出路是用元组替换你的4元素列表,甚至更好的用namedtuple,这是Python中着名的高性能容器。此外,在解释语言中应避免使用for循环。在python中,如果可能的话,可以使用理解而不是for循环来提高性能。你的清单不是太大,所以在高效的线路解释中获得的时间应该比破坏时更多。
对我来说,你的代码应该不起作用,但我不确定。
答案 1 :(得分:0)
假设你的例子是正确的,我认为没有理由你不能在一次通过中做到这一点,因为它们按年龄排序。如果您检查的最后一个子列表有太大差异,那么您之前不会知道任何事情,所以您应该保持当前子列表不被修改。
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 comprehensions是强大的工具,但它们不适合所有问题。