![](/img/trans.png)
[英]replace consecutive values of a list if they are equal to one single value of another list
[英]How to replace consecutive values in a list using another list as a reference?
我有一個這樣的列表:
list_target = [4, 5, 6, 7, 12, 13, 14]
list_primer = [3, 11]
所以list_target
由連續值塊組成,它們之間是值的跳轉(如從7
到12
)。 list_primer
由這些塊開頭的值組成。 list_primer
中的元素是在另一個進程中生成的。
我的問題是:對於list_primer
的每個元素,如何識別list_target
中的塊並用我想要的替換它們的值? 例如,如果我選擇將第一個塊中的值替換為1
,將第二個塊中的值替換為0
,則結果如下所示:
list_target_result = [1, 1, 1, 1, 0, 0, 0]
這是一個簡單的算法,它通過從頭到尾遍歷兩個列表來解決您的任務:
list_target = [4, 5, 6, 7, 12, 13, 14]
list_primer = [3, 11]
block_values = [1, 0]
result = []
for i, primer in enumerate(list_primer):
for j, target in enumerate(list_target):
if target == primer+1:
primer += 1
result.append(block_values[i])
else:
continue
print(result)
[1, 1, 1, 1, 0, 0, 0]
請注意,如果並非所有塊都有各自的引物,您可能會遇到麻煩,具體取決於您的用例。
def group_seq(l, list_primer):
" Find groups which are strictly increasing or equals next list_primer value "
temp_list = cycle(l)
temp_primer = cycle(list_primer)
next(temp_list)
groups = groupby(l, key = lambda j: (j + 1 == next(temp_list)) or (j == next(temp_primer)))
for k, v in groups:
if k:
yield tuple(v) + (next((next(groups)[1])), )
使用 group_seq 在 list_target 中查找嚴格遞增的塊
list_target = [4, 5, 6, 7, 12, 13, 14]
list_primer = [3, 11]
block_values = [1, 0]
result = []
for k, v in zip(block_values, group_seq(list_target, list_primer)):
result.extend([k]*len(v)) # k is value from block_values
# v is a block of strictly increasing numbers
# ie. group_seq(list_target) creates sublists
# [(4, 5, 6, 7), (12, 13, 14)]
print(result)
Out: [1, 1, 1, 1, 0, 0, 0]
這是一個適用於O(n)
的解決方案,其中n=len(list_target)
。 它假定您的 list_target 列表按照您描述的方式是連續的(在塊內增量為 1,在塊之間增量大於 1)。
它返回一個字典,其中每個塊的開頭作為鍵(潛在引物),該塊在 list_target 中的上下索引作為值。 然后訪問該字典是O(1)
。
list_target = [4, 5, 6, 7, 12, 13, 14]
list_primer = [3, 11]
block_dict = dict()
lower_idx = 0
upper_idx = 0
for i, val in enumerate(list_target): # runs in O(n)
upper_idx = i + 1
if i == len(list_target) - 1: # for last block in list
block_dict[list_target[lower_idx] - 1] = (lower_idx, upper_idx)
break
if list_target[i + 1] - list_target[i] != 1: #if increment more than one, save current block to dict, reset lower index
block_dict[list_target[lower_idx] - 1] = (lower_idx, upper_idx)
lower_idx = i + 1
結果如下:
print(block_dict) # quick checks
>>>> {3: (0,4), 11: (4,7)}
for p in list_primer: # printing the corresponding blocks.
lower, upper = block_dict[p] # dict access in O(1)
print(list_target[lower:upper])
>>>> [4, 5, 6, 7]
[12, 13, 14]
# getting the indices for first primer marked as in your original question:
list_target_result = [0] * len(list_target)
lower_ex, upper_ex = block_dict[3]
list_target_result[lower_ex: upper_ex] = [1]*(upper_ex-lower_ex)
print(list_target_result)
>>>> [1, 1, 1, 1, 0, 0, 0]
這是使用numpy
的解決方案。
import numpy as np
list_target = np.array([4, 5, 6, 7, 12, 13, 14])
list_primer = np.array([3, 11])
values = [1, 0]
ix = np.searchsorted(list_target, list_primer)
# [0,4]
blocks = np.split(list_target, ix)[1:]
# [array([4, 5, 6, 7]), array([12, 13, 14])]
res = np.concatenate([np.full(s.size, values[i]) for i,s in enumerate(blocks)])
# array([1, 1, 1, 1, 0, 0, 0])
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.