Изменение исходного параметра при передаче в функцию в качестве аргумента

Есть список словарей с временными интервалами:

[{'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 шт):

Автор решения: CrazyElf
segments=[]
segments[:] = segmentsList

Вы как-то затейливо копируете список, лучше уж так:

segments = segmentsList.copy()

Но в любом случае это получается "мелкая" копия. У вас список словарей. Список вы скопировали, он новый, а словари остались те же самые. Нужно и словари тоже копировать. Можно вручную, можно с помощью copy.deepcopy сразу "глубокую" копию списка словарей сделать и дальше уже работать с ней:

from copy import deepcopy
segments = deepcopy(segmentsList)
→ Ссылка
Автор решения: strawdog

На всякий случай решение с помощью 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}]
→ Ссылка