[英]Python check if list is present in list of lists for detecting cycles
我有一个大约 60000 个数据点的样本,并且在迭代算法中,在每个步骤中,根据某些标准,我要么“删除”(设置为 NaN)其中一个数据点,要么“添加”一个先前删除的数据点回到样本中(设置回其原始值)。 为了避免算法陷入死循环,每次迭代的样本应该总是不同的。 因此,我跟踪当前在每次迭代中删除的数据点,并将元素索引存储在列表中,如下所示:
现在在当前迭代 7 中,算法建议删除数组索引为 4 的元素,因此新的 state data_state_temp将是 [2,1,3]。 目前,它通过
flag_cycle = (data_state_temp in data_state_list)
该算法检查新的 state 以添加/删除不同的数组元素,直到flag_cycle
为False
,然后继续。
除此之外,它还没有完全工作,因为迭代 7 中的状态 [2,1,3] 和迭代 3 中的 [2,3,1] 是相同的,但列表不同(需要对它们进行排序或更好将新删除的数组元素插入到它们应该属于排序列表的位置),问题是算法变得非常慢。 在实践中,例如data_state_temp
的长度为 15000,而data_state_list
有 40000 个列表,通常长度会增加到 15000。
问题:
data_state_temp
是否在data_state_list
中时,它是否仅比较长度与data_state_temp
匹配的列表的列表元素(我希望如此),还是我们需要事先手动 select 这些列表? 如果你不关心过去状态的顺序——只是它曾经被访问过——那么让我们收集一set
所有过去的状态。 这给了我们一个固定的查找而不是线性查找in
(例如for needle in haystack
)
要使set
发挥其魔力,它必须与可散列类型一起使用。 简而言之, tuple
是不可变的,因此是可散列的,因此可以与set
一起使用。
from itertools import chain
# let's say we already have state that is 15000 long
data_states = set()
data_state = tuple(range(15000))
data_states.add(data_state)
# we loop until we decide on a new state
while data_state in data_states:
# either you decide to remove an element, say 42
# (can skip sort because the previous tuple was already sorted)
new_data_state = tuple(x for x in data_state if x != 42)
# or you decide to add an element, 9000
new_data_state = tuple(sorted(x for x in chain(data_state, [9000])))
data_state = new_data_state
# now commit this state to your history
data_states.add(new_data_state)
请注意,元组是不可变的,因此我们必须在创建元组之前先进行排序。 还要注意sorted(_)
形式创建一个副本,而_.sort()
执行就地排序。 由于我们将之前的 state 解析为生成器,因此后一种排序是不可能的,因为我们没有 memory。 所以选择前者。 然后将其输入tuple()
构造函数。
给定len(state) = n
:
new_data_state = tuple(sorted(x for x in chain(data_state, [9000])))
x for x in...
:具有n
操作的生成器sorted(...)
: 创建一个列表,填充n
个条目tuple(...)
: 创建一个元组,填充n
个条目步骤 1+2 发生在一次n
中。 然后对步骤 3 重复n
。每次state
迭代的总运行时复杂度为O{2n}
。
我上面列出的。 如果您记忆犹新,您可能会考虑更紧凑的 forms 代表state
。
例如,您可以将state
分块为由5000
个连续数字组成的3
块。 然后使用嵌套字典。 例如data_states[(x for x in range(5000)][(x for x in range(5000)] == <all the remaining digits>
通过这种方式,空间成本被摊销,使得15777
位元素的增量空间成本仅为15777 - 5000 - 5000 = 5777
位。 这本质上就是字典的作用。
是的,它执行长度匹配作为短路False
的第一个检查。 但是不,它仍然处理每一个元素。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.