Вычитание элементов из одного списка и извлечение элементов, соответствующих условию

Недавно я задал вопрос о поиске различий между двумя списками, которые соответствуют условию, но мне не удается изменить ПРИМЕР ЛЯМБДА-ВЫРАЖЕНИЯ ниже, чтобы сделать то же самое для элементов в одном списке:

A = ['12', '15', '20', '30']

filter(lambda a: all([abs(int(a) - int(b)) >= 5 for b in List1]), List2)

Где мой список отсортирован и может иметь разную длину. Цель состоит в том, чтобы изменить приведенное выше выражение, чтобы получить только те элементы, для которых разница TO ЛЮБОЙ ДРУГОЙ ЭЛЕМЕНТ в списке меньше или равна 5.

Где вывод, работающий в списке выше, должен быть:

newAList = ['12', '15', '20']

person Vince    schedule 14.07.2013    source источник
comment
Это уравнение было показано только в помощь всем, чтобы не начинать с нуля, мой вопрос относится только к показанному списку. Если вы предпочитаете, списки представлены здесь: output-thos?rq=1" title="как математически вычитать элементы из двух списков в python и выводить только thos"> stackoverflow.com/questions/17635995/   -  person Vince    schedule 14.07.2013
comment
Вы имеете в виду, что хотите сохранить пары последовательных элементов, которые имеют разницу не более 5? Или те предметы, где следующий элемент не более чем на 5 больше? Почему в вашем примере сохраняется 20, если следующий элемент равен 30, что более чем на 5 больше?   -  person andersschuller    schedule 14.07.2013
comment
Что означают только те элементы, разница между которыми меньше или равна 5? Какие предметы вы сравниваете? Если у вас есть ['2', '3', '14', '15'], что вы хотите вернуть?   -  person DSM    schedule 14.07.2013
comment
Я хочу сохранить любой элемент в списке, который имеет разницу с любым другим элементом, который меньше 5. Я оставил 20, потому что он меньше или равен 5 по сравнению с 15, а не 30. @DSM, вывод должен быть всем так как хотя разница между 14 и 2 составляет >5, разница между абс (14 и 15) не равна   -  person Vince    schedule 14.07.2013
comment
Есть ли дубликаты? А как насчет списка из одного элемента: проходит он или нет? (Совет: часто бывает проще, если вы пишете код, пусть и неэффективный, который дает вам желаемое поведение. Тогда никому не придется думать о крайних случаях.)   -  person DSM    schedule 14.07.2013
comment
Извините, хороший вопрос, поэтому списки отдельных элементов будут проходить через фильтр. Извините, у меня нет рабочего кода для публикации. Проблема с функциями понимания списка/лямбда заключается в том, что я не знаю, как указать элемент в дополнение к условному оператору.   -  person Vince    schedule 14.07.2013
comment
@Vince: понимание - это просто сжатый синтаксис для определенного цикла for, а лямбда-функция не делает ничего, чего не делает обычная функция. Как только у вас это получится, вы можете упростить его. Например, мне до сих пор не ясно, если бы список был ['2','10','10','20']`, вы бы хотели ['10','10'] или нет.   -  person DSM    schedule 14.07.2013
comment
@DSM: поскольку числа в моих списках являются местоположениями, дубликатов нет. Но если бы список был ['2','10','20'], вывод был бы ['10']   -  person Vince    schedule 14.07.2013


Ответы (2)


Это более короткая версия:

>>> A = ['12', '15', '20', '30']
>>> [x for x in A if len(A) == 1 or filter(lambda y: 0 < abs(int(y) - int(x)) <= 5,A)]
['12', '15', '20']
>>>
person Community    schedule 14.07.2013
comment
Что-то вроде [x for i,x in enumerate(A) if any(0 < abs(int(x)-int(y)) <= 5 for y in A[max(i-1,0):i+2]) or len(A)==1] будет линейным, а не квадратичным. - person DSM; 14.07.2013
comment
@DSM: Прости меня, но я не понимаю. Что означает квадратичный? Я никогда раньше не слышала этого термина, и мне интересно... - person ; 14.07.2013
comment
@iCodez: квадратичный означает вторую степень. Прямо сейчас, если вы удвоите длину A, ваш код будет занимать не вдвое, а в четыре раза больше времени (потому что для каждого элемента в A вы фильтруете каждый элемент в A, поэтому вы делаете ~len(A)*len( А) операции). - person DSM; 14.07.2013
comment
Кроме того, когда я меняю меньше чем на больше (только для понимания этого однострочника), это не работает. Почему это важно? - person Vince; 14.07.2013
comment
@Vince: Ну, это потому, что это допускает различия больше 5, и каждое число там имеет разницу с каким-то другим числом, которое больше 5. Например, 30 - 20 › 5. - person ; 15.07.2013

Основываясь на ваших комментариях, я считаю, что следующее понимание списка должно делать то, что вы ищете. Ключевые части:

  • Использование any вместо all, чтобы проверить, существует ли какой-либо элемент, который не более чем на 5 меньше или больше, чем текущий просматриваемый
  • Использование enumerate для гарантии того, что условие игнорирует просматриваемый в данный момент элемент — вы можете удалить вызовы enumerate и изменить сравнение на 0 < abs(int(a) - int(b)) <= 5, если знаете, что дубликатов нет.
  • Использование понимания списка вместо filter, чтобы сделать его более читабельным, на мой взгляд (только что) - должна быть возможность сделать то же самое с filter, однако

Код:

>>> A = ['12', '15', '20', '30']
>>> [a for i, a in enumerate(A) if any(j != i and abs(int(a) - int(b)) <= 5 for j, b in enumerate(A))]
['12', '15', '20']

Бьюсь об заклад, это будет довольно неэффективно для любого списка, намного большего, чем этот, поскольку вы будете перебирать список один раз для каждого элемента в списке. Однако, надеюсь, этого достаточно, чтобы дать вам отправную точку.

person andersschuller    schedule 14.07.2013
comment
Это больше, чем отправная точка, спасибо, что поработали со мной. Спасибо также за пояснения. Это работает для списков, состоящих из нескольких элементов, но не работает для отдельных элементов. Но я буду наслаждаться работой над этим. Ваше здоровье - person Vince; 14.07.2013
comment
Кроме того, когда я меняю меньше чем на больше (только для понимания этого однострочника), это не работает. Где в коде это меняется? - person Vince; 14.07.2013
comment
@Vince Что ты имеешь в виду, что это не работает? Он возвращает весь список, как и должно быть — в списке есть элемент для каждого элемента, который хотя бы на 5 больше или меньше (12 ‹-> 20, 15 ‹-> 30, 20 ‹-> 30). - person andersschuller; 15.07.2013