Главное меню
Мы солидарны с Украиной. Узнайте здесь, как можно поддержать Украину.

Вопросы о Python-е

Автор Квас, декабря 23, 2011, 00:14

0 Пользователи и 1 гость просматривают эту тему.

Квас

Пока, собственно, только один вопрос, но может, и другие появятся.

Никак не могу освоиться с этим языком.

В учебных целях придумал следующую задачку: есть строка, по структуре представляющая таблицу (например, | играет роль разделителя столбцов, а \n — разделителя строк). Требуется эту строку распарсить, то есть создать некий iterable объект, содержащий отдельные ячейки. Навроде двумерного массива. Вот никак не могу сообразить, в виде какого объекта это можно реализовать.

Вообще, насколько понимаю, такое паршенье необходимо должно предшествовать, например, всяким конвертациям таблицы: поскольку строки являются неизменяемыми величинами, использование в цикле оператора вида
str1 = str1 + str2
приводило бы к тому, что перелопачивается слишком много памяти. Следовательно, надо обрабатывать ячейки как элементы большого объекта, а потом за один раз делать конкатенацию. Правильно я говорю? В Lua, по крайней мере, учат делать так.
Пишите письма! :)

Demetrius

Цитата: Квас от декабря 23, 2011, 00:14
str1 = str1 + str2
Не делайте так. Переформулируйте задачу, чтобы использовать встроенные методы строк (строка.split('|'), например, или find): они работают быстрее (т.к. написаны на Си) и они удобнее.

Demetrius

Мне сейчас лень что-то думать, потому что у меня нет Пюфона для экспериментов под рукой и я боюсь соврать.

Python

Offtop
немного кложурного оффтопа:
Clojure 1.3.0
user=>
(def s
"asdf | fg |ggg
asd| asd|dd
sdfg| fff|gg")
#'user/s

user=>
(map #(seq (.split % "\\|")) (.split s "\n")) ;<--парсер
(("asdf " " fg " "ggg") ("asd" " asd" "dd") ("sdfg" " fff" "gg"))
Пролетареві ніколи вчити європейських мов, бодай би свою знати добре і на ній принести до своєї хати світло знання (Гнат Хоткевич)
ÆC CASALI NAXI PRASQURI: AHOV CÆRU, MERTVÆRI TÆ SLAVUTÆT!
Вони просили його: «Скажи: кетум», а він говорив: «сатем», і не міг вимовити правильно.
Хотелось бы также отметить, что "Питон" - это "мышиный язык" : "пи+тон". © АБР-2

Demetrius


Python

Научившись на них думать, начинаешь понимать весь ужас нелиспов.
Пролетареві ніколи вчити європейських мов, бодай би свою знати добре і на ній принести до своєї хати світло знання (Гнат Хоткевич)
ÆC CASALI NAXI PRASQURI: AHOV CÆRU, MERTVÆRI TÆ SLAVUTÆT!
Вони просили його: «Скажи: кетум», а він говорив: «сатем», і не міг вимовити правильно.
Хотелось бы также отметить, что "Питон" - это "мышиный язык" : "пи+тон". © АБР-2

Квас

Цитата: Demetrius от декабря 23, 2011, 00:20
Цитата: Квас от декабря 23, 2011, 00:14
str1 = str1 + str2
Не делайте так. Переформулируйте задачу, чтобы использовать встроенные методы строк (строка.split('|'), например, или find): они работают быстрее (т.к. написаны на Си) и они удобнее.

Я же и пишу, что так нельзя делать. Если начать с пустой строки и прибавлять сто раз по символу, то в результате постоянного создания новых строк используется, грубо говоря, (1+2+...+100) б ≈ 5 кб памяти.

Поэтому мне и кажется, что нужно ячейки сделать элементами некоторого аналога двумерного массива, после чего можно пользоваться, например, операцией join.
Пишите письма! :)

Bhudh

Так можно сначала разделить исходную строку по разделителю строк, а потом — в цикле — по разделителям ячеек...

В Pythonʼе же есть аналог jay-esʼового
Цитата: var s = "a1b2c3d".split(/\d/);
вернет массив ["a", "b", "c", "d"].


?
Пиши, что думаешь, но думай, что пишешь.
MONEŌ ERGŌ MANEŌ.
Waheeba dokin ʔebi naha.
«каждый пост в интернете имеет коэффициент бреда» © Невский чукчо

RawonaM

Цитата: Demetrius от декабря 23, 2011, 00:20
Цитата: Квас от декабря 23, 2011, 00:14str1 = str1 + str2
Не делайте так. Переформулируйте задачу, чтобы использовать встроенные методы строк (строка.split('|'), например, или find): они работают быстрее (т.к. написаны на Си) и они удобнее.
Не понял. Оператор "плюс" - не встроенный метод?
Тогда есть более встроенный метод: ''.join([str1,str2]).

RawonaM

Честно сказать, не понял проблему и что требуется.

Почему бы в качестве "что-то типа двумерного массива" не использовать например двумерный массив? Ну или дишкнари с киями в виде таплов по два.

Делаем просто два раза сплит на эту строку (по '\n' и по '|') и все.

Bhudh

Пиши, что думаешь, но думай, что пишешь.
MONEŌ ERGŌ MANEŌ.
Waheeba dokin ʔebi naha.
«каждый пост в интернете имеет коэффициент бреда» © Невский чукчо

RawonaM

Цитата: Bhudh от декабря 23, 2011, 14:03
Я это и предложил.
Значит я поддерживаю.

Цитата: Квас от декабря 23, 2011, 10:11
Я же и пишу, что так нельзя делать. Если начать с пустой строки и прибавлять сто раз по символу, то в результате постоянного создания новых строк используется, грубо говоря, (1+2+...+100) б ≈ 5 кб памяти.
А почему это вас волнует? Откуда вообще у вас такая инфа? :) Это же детали имплементации языка, а не часть языка.
Я не знаю как работает гарбаге цоллецтор в питоне (в каком из них?), но почему бы ему своевременно обрывки не подчищать, чтобы столько памяти не скапливалось? После выполенния str1 = str1 + str2, то на что раньше str1 указывал уже ничем не адресовано и подлежит удалению. Может новый стр1 вообще на его же место запишется.

Цитата: Квас от декабря 23, 2011, 10:11
Поэтому мне и кажется, что нужно ячейки сделать элементами некоторого аналога двумерного массива, после чего можно пользоваться, например, операцией join.
Запутался. Вам нужно построить такую строку или ее распарсить?

Bhudh

Распарсить, обработать ячейки по отдельности и построить обратно, насколько я понял.
Пиши, что думаешь, но думай, что пишешь.
MONEŌ ERGŌ MANEŌ.
Waheeba dokin ʔebi naha.
«каждый пост в интернете имеет коэффициент бреда» © Невский чукчо

RawonaM

Ну строится обратно в обратном порядке, вместо двух сплитов два джоина.

Bhudh

Погоди. А джойн берёт ряд массива в отдельности? Хотя что я, если у нас сплиты, то у нас одномерный массив...
Пиши, что думаешь, но думай, что пишешь.
MONEŌ ERGŌ MANEŌ.
Waheeba dokin ʔebi naha.
«каждый пост в интернете имеет коэффициент бреда» © Невский чукчо

RawonaM

И вообще питон это почти математика, там че хочешь берется. Пишешь как обычно пишут математики {f|f \in S} [f for f in S] и все дела.

Квас

Цитата: RawonaM от декабря 23, 2011, 13:56
Почему бы в качестве "что-то типа двумерного массива" не использовать например двумерный массив? Ну или дишкнари с киями в виде таплов по два.

Надо попробовать.

Цитата: RawonaM от декабря 23, 2011, 13:56
Честно сказать, не понял проблему и что требуется.
Хочу вот это:
Цитата: Bhudh от декабря 23, 2011, 14:14
Распарсить, обработать ячейки по отдельности и построить обратно, насколько я понял.
но не мог сообразить, как это по-человечески сделать. Алгоритмически просто, но начинаю писать — дальше «def» не идёт.

Цитата: RawonaM от декабря 23, 2011, 14:09
Цитата: Квас от декабря 23, 2011, 10:11Я же и пишу, что так нельзя делать. Если начать с пустой строки и прибавлять сто раз по символу, то в результате постоянного создания новых строк используется, грубо говоря, (1+2+...+100) б ≈ 5 кб памяти.
А почему это вас волнует? Откуда вообще у вас такая инфа? :) Это же детали имплементации языка, а не часть языка.

Я читал Programming in Lua, и там был пример, когда последовательное добавление строк к строке-результату работает порядка 2 с, а объединение большого количества строк — элементов таблицы происходит мгновенно благодаря алгоритму ханойской башни или чего-то навроде. Это потому, что строки в Lua — неизменяемые объекты. В Pythone — тоже (согласно туториалу), поэтому я и соображаю, что идеологически верно за раз объединять кучу строк.
Пишите письма! :)

arseniiv

Цитата: RawonaM от декабря 23, 2011, 13:56
Ну или дишкнари с киями в виде таплов по два.
Понял только на третьем прочтении.

Quase, split как раз будет быстрее, чем ручная функция-парсер.

Demetrius

Цитата: RawonaM от декабря 23, 2011, 13:47
Не понял. Оператор "плюс" - не встроенный метод?
Тогда есть более встроенный метод: ''.join([str1,str2]).
Оператор плюс-то встроенный, но, как я понял, Квас собрался проходиться по каждому символу строки и прибавлять его к строке-результату.

А вообще да, РавонаМ прав, проще всего так:
a="""11|12|13
21|22|23
31|32|33"""

t = [x.split("|") for x in a.split("\n")]

Квас

Цитата: arseniiv от декабря 23, 2011, 19:36
Quase, split как раз будет быстрее, чем ручная функция-парсер.

Я не против. Вопрос состоял в том, каким типом данных представить двумерный массив строк.
Пишите письма! :)

Квас

Цитата: Demetrius от декабря 23, 2011, 19:43
Цитата: RawonaM от декабря 23, 2011, 13:47Не понял. Оператор "плюс" - не встроенный метод?
Тогда есть более встроенный метод: ''.join([str1,str2]).
Оператор плюс-то встроенный, но, как я понял, Квас собрался проходиться по каждому символу строки и прибавлять его к строке-результату.

Ну, не по символу, но можно представить, что от одной строки-таблицы откусываются, например, ячейки, и из них составляется другая строка. Что по моему разумению неграмотно.
Пишите письма! :)

Demetrius

Цитата: Квас от декабря 23, 2011, 19:45
Я не против. Вопрос состоял в том, каким типом данных представить двумерный массив строк.
Списком списков же. Если будут проблемы с производительностью, тогда уже делать итератор с yield'ами.

arseniiv

Цитата: Квас от декабря 23, 2011, 19:45
Я не против. Вопрос состоял в том, каким типом данных представить двумерный массив строк.
А, ну так вон тогда у Deme. в самом конце получается двумерный массив.

Demetrius

Неправда, у Deme. получается список списков. Если честно, я вообще не знаю, как в Пюфоне сделать массив.

arseniiv

Ну это я метаординарно говоря. Решил не читать, какие там типы, когда вопрос не такой конкретный.

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

Обратите внимание: данное сообщение не будет отображаться, пока модератор не одобрит его.

Имя:
Имейл:
Проверка:
Оставьте это поле пустым:
Наберите символы, которые изображены на картинке
Прослушать / Запросить другое изображение

Наберите символы, которые изображены на картинке:

√36:
ALT+S — отправить
ALT+P — предварительный просмотр