Удаление элементов в списке, которые находятся ближе, чем N друг от друга

#python #list

#python #Список

Вопрос:

Предположим, у меня есть следующий список:

 a = [0,5,10,11,15,22]
  

…и я хочу убедиться, что элементы списка всегда находятся на расстоянии не менее 5 друг от друга, как я мог это сделать?

ожидаемый результат:

 [0,5,10,15,22]
  

То, что я пробовал, не очень похоже на pythonic:

 a.sort()
prev_elem = a[0]
new_list = []
for elem in a[1:]:
    if abs(prev_elem-elem) >= 5:
         new_list.append(prev_elem)
    # update
    prev_elem = elem
  

Комментарии:

1. Почему мои вопросы о переполнении стека получают отрицательные отзывы без объяснения причин

2. Пожалуйста, более конкретно о том, как вы удаляете элементы, когда они плотно упакованы. Кроме того, запрос на «более Pythonic» больше похож на запрос на проверку кода. Вместо этого, пожалуйста, сосредоточьтесь на одном элементе, который, по вашему мнению, следует сделать лучше. В противном случае ваш вопрос упрощается до «переписать мой код».

Ответ №1:

Вы можете сделать это с помощью нескольких очень небольших изменений в вашем существующем коде.

Измененные строки прокомментированы ниже.

 a = [0,5,10,11,15,22]

a.sort()
prev_elem = a[0]
new_list = [prev_elem]  # <====== initialise with one element
for elem in a[1:]:
    if abs(prev_elem-elem) >= 5:
         new_list.append(elem)  # <===== append the new element
         prev_elem = elem  # <===== indented more (inside "if" block)

print(new_list)
  

Это дает:

 [0, 5, 10, 15, 22]
  

Комментарии:

1. if abs(new_list[-1]-elem) >= 5 сокращает две строки и позволяет избежать жонглирования prev_elem в более сложных циклах.

2. Правдоподобно, но целью этого ответа было показать минимум, который необходимо было изменить из исходного кода OP. Я рад оставить это другим ответам, чтобы предложить наиболее эффективное решение.

Ответ №2:

Выполнить итерацию по списку. Если arr[i] 5 > arr[i 1], то удалите arr[i 1]. Что-то вроде следующего кода.

 i = 0
while i < len(arr)-1:
    if arr[i] 5 > arr[i 1]:
        del arr[i 1]
    else:
        i =1
  

Определенно есть более чистые и эффективные способы сделать это, но это должно сработать.

Комментарии:

1. 1 , но как насчет a = [10,5,0] ? Все они находятся на расстоянии 5, но ваш код этого не получит. Если вы отсортируете список заранее, ваш код должен работать.

2. Ну, код предполагает, что он отсортирован в порядке возрастания. Для эффективного кода вам определенно нужно сначала отсортировать его. Вы также можете отсортировать его в порядке убывания, и код просто немного изменится.

Ответ №3:

Обратите внимание, что это псевдокод, где n — длина массива с именем arr:

 for i = 1 to n
    if (arr[i] - arr[i - 1] >= 5 OR arr[i] - arr[i - 1] <= -5)
        //remove arr[i]
  

Ответ №4:

Один из способов сделать это:

 a = [0,5,10,11,15,22]
result = []

for i, num in enumerate(a):
    if i == 0:
        result.append(num)
        continue
    if 3 <= abs(num - a[i-1]):
        result.append(num)

# [0,5,10,11,15,22] -> [0, 5, 10, 15, 22]
# [10, 9, 5, 0] -> [10, 5, 0]
# [10, 14, 9, 11, 5, 7, 0] -> [10, 14, 9, 5, 0]
  

Редактировать:

Я понял, что это можно сделать проще. Использование среза и распаковки позволяет избежать ошибки индекса в случае пустого списка:

 result = [*a[0:1]]      

for num in a[1:]:
    if 3 <= abs(num - result[-1]):
        result.append(num)