Понимание Python с разным количеством элементовPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Понимание Python с разным количеством элементов

Сообщение Anonymous »

Общая проблема
У меня есть случай, когда я генерирую понимание элемента с кардинальностью, отличной от входного источника. Эта мощность не должна быть кратной исходной (определяемой данными), а должна определяться условиями. Некоторые элементы исходного источника могут быть преобразованы в один элемент в месте назначения, тогда как другие могут быть преобразованы в несколько элементов или даже ни в один.
Существующие подходы
Несколько вопросов касаются смежных ситуаций, но не совсем одинаковых:
  • Понимание списка: возврат двух (или более) элементов для каждого элемента [дубликат]
    Как я могу получить простой результат из списка вместо вложенного списка?
(Автор: кстати, я считаю, что эти два вопроса не дублируют друг друга. Они затрагивают разные, хотя и частично пересекающиеся проблемы, и хотя решения в некоторой степени взаимозаменяемы, сами вопросы таковыми не являются.)
Первый из них обращается к пониманию, длина которого в точности кратна длине источника. Второй обеспечивает способ создания плоских списков из результата, который имел списки списков, с помощью сокращения или с помощью двойной итерации в самом понимании. Обратите внимание, что в этом случае оба на самом деле будут создавать нерегулярное количество элементов (не кратное исходному), но на основе данных, а не на основе условий.
< h1>Простая проблема
У меня есть список строк, в которых будет число или два числа, разделенные дефисом, скажем:

Код: Выделить всё

['1', '2', '2-3', '3-1', '4-5']
Желаемый результат:

Код: Выделить всё

['1', '2', '2', '3', '3', '1', '4', '5']
Как видите, никакой зависимости по мощности нет (кроме того, что она растет).
Решение 1 — паршивое

Код: Выделить всё

>>> a = ['1', '2', '2-3', '3-1', '4-5']
>>> '-'.join(a)
'1-2-2-3-3-1-4-5'
>>> '-'.join(a).split('-')
['1', '2', '2', '3', '3', '1', '4', '5']
Это предполагает две вещи:
  • Я использую списки. На самом деле в моем упражнении используются словари, списки кортежей и тому подобные парные коллекции данных. Я мог бы присоединиться к некоторым из этих компонентов, но полностью потерял бы связь с другими частями исходных данных.
  • Это хакерски, некрасиво и, вероятно, неэффективно.
Решение 2 — уменьшить

Код: Выделить всё

>>> a = ['1', '2', '2-3', '3-1', '4-5']
>>> reduce(lambda acc, elem: acc+elem, (x.split('-') for x in a))
['1', '2', '2', '3', '3', '1', '4', '5']
Этот вариант лучше предыдущего, но он по-прежнему основан на данных. Это также сглаживание списка списков, хотя и слегка оптимизированное за счет хитрого введения внутреннего генератора вместо внутреннего понимания.
Более сложная проблема
Что, если бы у меня был просто список чисел и я хотел бы генерировать ответы разной длины в зависимости от значений? Здесь я перехожу к спискам чисел, чтобы не мешать ответам на манипуляции со строками.
Теперь мне нужен список результатов, в который помещается число, если оно нечетное, и число и его половина, если даже:

Код: Выделить всё

>>> a = [1, 2, 3, 4, 5]
>>> # Magic code
[1, 1, 2, 3, 2, 4, 5]
Итак, в зависимости от условия — x % 2 == 0, в данном случае — я хочу добавить в список одно или два числа.
Решение 0. Не хватает старого доброго C?

Код: Выделить всё

>>> a = [1, 2, 3, 4, 5]
>>> res = []
>>> for x in a:
...   if x % 2:
...     res.append(x)
...   else:
...     res.append(x//2)
...     res.append(x)
...
>>> res
[1, 1, 2, 3, 2, 4, 5]
Список оскорблений в этом решении включает «анти-питоновское», «уродливое» и т. д. Оно работает, но, как я всегда говорю: «Если «это работает», то лучше всего/ единственное хорошее, что вы можете сказать о своем коде..."
Решение 1. Сглаживание многомерного списка

Код: Выделить всё

>>> a = [1, 2, 3, 4, 5]
>>> [x if x % 2 else [x//2, x] for x in a]
[1, [1, 2], 3, [2, 4], 5]
Теперь у меня есть список, содержащий как элементы, так и списки. Мой вариант сокращения будет немного сложнее, поэтому я собираюсь составить их все списками:

Код: Выделить всё

>>> a = [1, 2, 3, 4, 5]
>>> [[x] if x % 2 else [x//2, x] for x in a]
[[1], [1, 2], [3], [2, 4], [5]]
Теперь я могу уменьшить:

Код: Выделить всё

>>> a = [1, 2, 3, 4, 5]
>>> reduce(lambda acc, elem: acc+elem, ([x] if x % 2 else [x//2, x] for x in a))
[1, 1, 2, 3, 2, 4, 5]
Еще раз работает, но не напрямую. Он по-прежнему создает итерацию для сокращения.
Мне нужно решение, которое просто передает в цель переменное количество элементов, рассчитанное на основе каждого исходного элемента. Причина, по которой это должно быть похоже на выражение, заключается в том, что оно встроено в более широкое выражение. Поэтому, несмотря на мое огромное уважение к ним, пожалуйста, никаких императивных решений Кернигана и Ритчи.
Редактировать
Некоторые участники упомянули, что я «готов использовать сокращение ». Я пытался дать понять, что ищу что-то другое. Мне нравится сокращение и все функциональные возможности, но использование ресурсов оправдано только тогда, когда данные поступают «как есть».
Что касается читаемости и необходимости , ничего против. Я работаю целый день на Python и C. Просто for больше говорит о том, «как», тогда как понимание больше о том, «что». Я думаю, что читаемость — это, в конечном счете, вопрос предпочтений:

Код: Выделить всё

Beautiful is better than ugly.
Explicit is better than implicit.
...
Некоторые комментаторы упомянули «реальный мир», «готовность к производству» и «читабельность». Тем я рекомендую прочитать исходный код некоторых библиотек, которые вы используете каждый день. Я делаю, и это отличное упражнение. Вам также следует попробовать PDB и проверить такие вещи, как длина кода, использование памяти и т. д.
Я хотел бы особо отметить и поблагодарить jsbueno. Вы делаете правильные выводы. доход потрясающий, и это часть моей личной цепочки инструментов для повышения производительности, поскольку «Pythonicity» — только моя цель №2.
Еще одно спасибо Догберту. Ваше предложение было тем, что я считаю правильным решением. Должен признаться, что у меня уже было решение, когда я опубликовал это, и разница между вашим и моим просто квадратная и круглая.
В остальном, если подход «пока это работает", то я думаю, что многие вопросы повторяются, и да, путь из Кембриджа в Лондон может проходить через Гонолулу, "пока мы туда добираемся".
Я злоупотребил этим термином «Пифонический», даже не зная на 100%, что это значит. Я пытался не использовать библиотеки и оставить их «родными».
Вот мое решение:

Код: Выделить всё

>>> a = [1, 2, 3, 4, 5]
>>> [ x for i in a for x in ((i,) if i % 2 else (i // 2, i)) ]
[1, 1, 2, 3, 2, 4, 5]
Одна строка.


Подробнее здесь: https://stackoverflow.com/questions/789 ... f-elements
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»