Изменение исходного параметра при передаче в функцию в качестве аргумента
Есть список словарей с временными интервалами:
[{'start': 12.4, 'end': 12.8}, {'start': 14.0, 'end': 15.5}, {'start': 15.7, 'end': 16.2}, {'start': 16.5, 'end': 17.1}, {'start': 17.9, 'end': 18.5}, {'start': 20.5, 'end': 21.0}, {'start': 22.1, 'end': 22.4}, {'start': 23.0, 'end': 23.7}, {'start': 24.9, 'end': 27.8}, {'start': 29.2, 'end': 34.0}, {'start': 34.5, 'end': 35.4}, {'start': 36.5, 'end': 37.1}, {'start': 37.7, 'end': 38.5}, {'start': 38.7, 'end': 40.4}, {'start': 43.5, 'end': 44.3}, {'start': 45.2, 'end': 48.1}]
Мной написана функция, которая объединяет временные интервалы, если расстояние между ними меньше или равно заданной длительности, а также выравнивает длину интервалов, если он меньше параметра chunk_size
def combineTimeSegments(segmentsList, chunk_size: int = 2):
segments = []
segments[:] = segmentsList
counter = 0
while counter < len(segments):
try:
cur_segment = segments[counter]
next_segment = segments[counter+1]
diff_length_segment = cur_segment['end'] - cur_segment['start']
length_between_segments = next_segment['start'] - cur_segment['end']
if length_between_segments <= chunk_size:
cur_segment['end'] = next_segment['end']
new_segments = [seg for seg in segments if seg != next_segment]
segments.clear()
segments[:] = new_segments
counter -= 1
if counter < 0:
counter = 0
continue
else:
if diff_length_segment < chunk_size:
cur_segment['end'] = cur_segment['start'] + chunk_size
except Exception as err:
pass
counter += 1
return segments
После вызова функции получается корректный результата:
[{'start': 12.4, 'end': 40.4}, {'start': 43.5, 'end': 48.1}]
Однако, изменяется исходный список в первом сегменте. Что я делаю не так?
Ответы (2 шт):
segments=[]
segments[:] = segmentsList
Вы как-то затейливо копируете список, лучше уж так:
segments = segmentsList.copy()
Но в любом случае это получается "мелкая" копия. У вас список словарей. Список вы скопировали, он новый, а словари остались те же самые. Нужно и словари тоже копировать. Можно вручную, можно с помощью copy.deepcopy сразу "глубокую" копию списка словарей сделать и дальше уже работать с ней:
from copy import deepcopy
segments = deepcopy(segmentsList)
На всякий случай решение с помощью pandas:
import pandas as pd
data = [{'start': 12.4, 'end': 12.8}, {'start': 14.0, 'end': 15.5}, {'start': 15.7, 'end': 16.2}, {'start': 16.5, 'end': 17.1},
{'start': 17.9, 'end': 18.5}, {'start': 20.5, 'end': 21.0}, {'start': 22.1, 'end': 22.4}, {'start': 23.0, 'end': 23.7},
{'start': 24.9, 'end': 27.8}, {'start': 29.2, 'end': 34.0}, {'start': 34.5, 'end': 35.4}, {'start': 36.5, 'end': 37.1},
{'start': 37.7, 'end': 38.5}, {'start': 38.7, 'end': 40.4}, {'start': 43.5, 'end': 44.3}, {'start': 45.2, 'end': 48.1}]
df = pd.DataFrame(data)
delta = 2
df["boundary"]=(df["start"]-df["end"].shift()).gt(delta).ffill().cumsum()
res = [g.to_dict("list") for i, g in df.groupby("boundary")[["start", "end"]]]
res = [{"start": g["start"][0], "end":g["end"][-1]} for g in res]
res:
[{'start': 12.4, 'end': 40.4}, {'start': 43.5, 'end': 48.1}]