LINUX.ORG.RU

Переместить строку в конец файла

 


0

2

Добрый вечер! Помогите на питоне! Открываю файл и иду по нему по строка через for line in open(«file»):

потом когда, для какой-то строки line выполнилось какое-то условие, надо перенести эту строку в конец файла. Подскажите как это сделать? спасибо!

Первое, что приходит в голову:

  • Два списка head и tail.
  • Если условие выполнилось, пушишь в tail, иначе в head.
  • Складываешь списки, объединяешь в строку ('\n'.join(head + tail)) и готово.
Kilte ★★★★★
()

Что за задача? Если что-то сложнее выбора из списка фильма на вечер, возможно, имеет смысл пересмотреть концепцию.

mix_mix ★★★★★
()

больше на сортировку по неизвестному условию похоже

anonymous
()

Kilte дело говорит.

f = open('file', 'r+')
lines = f.readlines()
f.seek(0)

temp = []

for l in lines:
    if len(l) > 25:
        temp.append(l)
    else:
        f.write(l)

f.writelines(temp)

f.truncate()
f.close()
anonymous
()
Ответ на: комментарий от anonymous

Наркоманы, чтоли, всё в памяти хранить?

grep -v PATTERN file > ._tmp
grep PATTERN file >> ._tmp
mv ._tmp file

Тут с практической точки зрения очень важна последняя операция, f.truncate() делать не стоит.

mashina ★★★★★
()
Ответ на: комментарий от mashina

в памяти хранить

А тебе памяти жалко, что ли? А дорогого SSD не жалко?

f.truncate() делать не стоит

Стоит, если человек вдруг не захочет писать какую-то строку в файл.

anonymous
()
Ответ на: комментарий от mashina

он же пишет

для какой-то строки line выполнилось какое-то условие

это не обязательно должен быть матчинг строк

например (пример на JS, так как пистон не знаю)


condition = function(str){return eval(str) === 10}

txt = fs.readFileSync("file.txt", "utf8")
txt = txt.replace(/.*/g, function(str){
  if(condition(str)) {lastString = str; return "XXXXX"}
  return str
})

txt = txt.replace(/XXXXX\r?\n/, "")
if(global.lastString) txt = txt.replace(/$/, lastString)

fs.writeFileSync("file.txt", txt)

Что то такое должно быть, наверное.

newquestion
()
Ответ на: комментарий от newquestion

это не обязательно должен быть матчинг строк

А ещё это не должен быть grep, да? Смотреть в трёх строчках нужно было на то, что нельзя писать в файл из которого же и читаешь. А твой пример вообще ахтунговый, он жрёт больше всех памяти и при этом ещё медленнее всех.

mashina ★★★★★
()
Ответ на: комментарий от mashina

А твой пример вообще ахтунговый, он жрёт больше всех памяти и при этом ещё медленнее всех.

какой бред, для одноразовой замены. Вообще, удобная позиция, не умеешь ничего толкового, болтай про оптимизацию все время, авось за умного проконаешь. BTW, где ты там жер памяти нашел? В том что файл в память грузишь, или че? Ты на каком компе то сидишь, что загрузка файла для тебя оверхед?

newquestion
()
Ответ на: комментарий от mashina

А зачем ты файлы ._tmp скрытыми делаешь? Ты же все равно их удаляешь.

newquestion
()
Ответ на: комментарий от newquestion

Кхм, не удержался :)

В том что файл в память грузишь, или че?

Скажи это wireshark'у например. Скачай только перед этим пару 4k киношек, лучше, через торрент. А потом, сравни с tshark'om.

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

pon4ik ★★★★★
()
Ответ на: комментарий от anonymous

А в общем случае твоё решение имеет больший шанс упасть с неконсистентными данными на выходе:)

А автор не указал ограничений ни на размер ни на железо.

pon4ik ★★★★★
()
Ответ на: комментарий от pon4ik

твоё решение

А где твоё решение, максимально приближенное к условиям ТСа, которое можно было бы вот так же легко обсудить?

anonymous
()
Ответ на: комментарий от mashina

Наркоманы, чтоли, всё в памяти хранить?

Я, например, не могу знать, насколько большой объём данных нужно перелопатить, потому предложил, так сказать, решение в лоб.

Kilte ★★★★★
()

По мере чтения file1 пиши в file2, потом mv file2 file1.

true_admin ★★★★★
()
Ответ на: комментарий от anonymous

Ну, я за уменьшение энтропии вселенной, поэтому моё решение это таки grep.

Ну, максимум можно тот код к однострочнику свести:

p=pattern grep -v "$p" file > .tmp; grep "$p" >> .tmp; mv .tmp file #Key to search in history

Хотя, тут есть свои минусы, с одной стороны такую команду можно тупо в истории потом искать, с другой стороны менее читабельно.

Тут уже зависит от юзекейса надо ли его пихать в скрипт или лучше так.

pon4ik ★★★★★
()
Последнее исправление: pon4ik (всего исправлений: 1)
Ответ на: комментарий от pon4ik

я за уменьшение энтропии

Тогда тебе лучше было бы избежать постить камент. Во-вторых, мог бы чего-нибудь своего привнести.

(f=file; p=pat; grep -v $p $f; grep $p $f) > f
anonymous
()
Ответ на: комментарий от newquestion

BTW, где ты там жер памяти нашел?

.replace, дебила кусок.

Вообще, удобная позиция, ничего не соображая можно писать всякое говно, оправдывая что у тебя никогда не будет реальной задачи, как например нарисовать круг. Остается только передавать zip через ajax.

anonymous
()
Ответ на: комментарий от Virtuos86

BTW, иммутабельность тут не причем. Допустим, к массиву примеряем map, там тоже порождается новый массив , хотя массивы муттабельны. От операции зависит.

newquestion
()
Ответ на: комментарий от newquestion

А старый куда девается?

Ты серьезно задаешь этот вопрос? Я думаю, он собирается сборщиком мусора во время следующего «остановки мира».

Virtuos86 ★★★★★
()
Ответ на: комментарий от newquestion

У массивов в Питоне есть методы, которые меняют исходный массив, и есть методы, которые создают новый массив. Вот из-за вторых массивы в Питоне являются мутабельными, если же использовать первые, массивы вполне можно рассматривать как неизменяемые объекты.

Virtuos86 ★★★★★
()
Ответ на: комментарий от Virtuos86

массивы вполне можно рассматривать как неизменяемые объекты

В том смысле, что не порождается новых объектов, и, соответственно, не тратится память.

Virtuos86 ★★★★★
()
Ответ на: комментарий от Virtuos86

что ты несешь? наоборот, неизменяемые будут расходовать память, так как создается копия, и уже над ней совершается операция. Если на оригинал будут ссылки, в памяти будут висеть оба экземпляра.

newquestion
()
Ответ на: комментарий от newquestion

На практике, между появлением неиспользуемых объектов, которые потеряли ссылки на себя, и запуском GC может пройти неопределенное время, за которое количество таких объектов может принять ощутимое значение, это раз. Во-вторых, зачем создавать лишнюю работу сборщику мусора, увеличивая «тормоза» виртуальной машины? А в общем случае, всё зависит, от исходных условий: ограничения по процессорному времени, по памяти и т.д. В ОП задача может подразумевать очень большой файл, и тогда массовое создание строк может выжрать доступную память, например.

Virtuos86 ★★★★★
()
Ответ на: комментарий от newquestion

наоборот, неизменяемые будут расходовать память, так как создается копия, и уже над ней совершается операция

А зачем тогда ты задавал этот вопрос, если тебе ясен ответ:

А теперь поясни, тупое педрило, как по-твоему replace отжирает память.

Virtuos86 ★★★★★
()
Ответ на: комментарий от Virtuos86

Это был риторический вопрос. Нет там расхода памяти. Этот лошок берега попутал. Расходы на GC к расходу памяти не относится.

newquestion
()
Ответ на: комментарий от newquestion

Не за что. С дурачками так и работают: долго и терпеливо объясняют прописные истины. Правда, всё-равно не всегда помогает.

Virtuos86 ★★★★★
()
Ответ на: комментарий от Virtuos86

Да не, ты строчишь тут прописные истины потому что знанием нетривиальных истин ты похвастаться не можешь, а похвастаться чем то хочется.

newquestion
()
Ответ на: комментарий от mashina

он жрёт больше всех памяти

Кстати

grep -v PATTERN file > ._tmp # записали в файл и бросили на него ссылку tmp
grep PATTERN file >> ._tmp # дописали в файл
mv ._tmp file # удалили ссылку ._tmp установили ссылку file
Вопрос на засыпку. Куда делся оригинал файла file? Ответ: остался висеть в памяти.

В твоем *кошерном примере* ровно такие же накладные расходы, как и в моем.

newquestion
()
Ответ на: комментарий от newquestion

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

anonymous
()
Ответ на: комментарий от anonymous

Если мы применим этот алгоритм к пачке файлов в цикле, будет тот же самый расход. А если учесть, что в оси сборщик примитивен, расход будет еще больше. По-принципу новые файлы записываются, а старые остаются. Разница только в том, что файлы тут не считываются целиком в буфер.

newquestion
()
Ответ на: комментарий от anonymous

Не знаю, по объему есть ли там ограничения, но суть, по идее такая, несколько терабайт будут так же висеть, если нет дополнительных механизмов на уровне оси для отдельного контроля за большими файлами. Этого я не знаю.

newquestion
()
Ответ на: комментарий от newquestion

Какой цикл родной, у тебя уже на первой итерации oops случится. Посоны, мне кажется у нас тут новое пробитие дна анонiмусом намечается.

anonymous
()
Ответ на: комментарий от anonymous

Ты похоже, не понимаешь о чем я говорю. Есть разница, одно дело, построчная обработка, и совсем другое — построчная обработка с промежуточной записью в файл.

newquestion
()
Ответ на: комментарий от newquestion

Сука, это надо в рамку и постить в каждый твой тред, дно торжественно пробито! Вопросов больше не имею.

anonymous
()
Ответ на: комментарий от anonymous

В том что памяти в этом случае не хватит (точней может не хвтить) в любом случае, так как просто не хватит памяти для записи нового файла, тут ты, допустим прав, это, как-бы, самоочевидно. Но какое это имеет отношение к теме? Это только косвенно подтверждает мою правоту. Поциэнт ведь *думает*, что в его алгоритме память не расходуется.

newquestion
()
Ответ на: комментарий от newquestion

Куда делся оригинал файла file? Ответ: остался висеть в памяти.

Прочитал твои бредни от этого идалее, не думал что такие клинически сказочные личности на ЛОРе существуют. Несколько удивительно что на такой простой вопрос в треде дали столько некорректных решений и речь даже не про память.

В твоем *кошерном примере* ровно такие же накладные расходы, как и в моем.

Нет, не такие же. Тебе вообще стоило бы заткнуться и перейти в режим ro лет на десять, ведь твой пример даже не делает того, что просили изначально - т.е. не переносит некоторые строчки выборочно в конец файла.

mashina ★★★★★
()
Ответ на: комментарий от mashina

Пример был заточен под строго определенные строки, поскольку используется предикат. Если ты даже этот код не смог осилить, говорить не о чем. В игнор за экстремальную тупость.

newquestion
()
Ответ на: комментарий от newquestion

Если ты даже этот код не смог осилить, говорить не о чем.

Не тупи. У тебя в коде сначала строки совпадающие с условием заменяются на «XXXXX», запоминается последняя совпавшая.

Затем убираются все строки, оканчивающиеся на «XXXXX» и запомненная строка дописывается в конец.

В общем случае, если больше одной строки совпадает с условием, то все кроме последней удалятся, но не добавятся в конец. Также, если уже есть строки, заканчивающиеся на «XXXXX», то они удалятся.

Очень плохой алгоритм.

monk ★★★★★
()
Ответ на: комментарий от monk

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

newquestion
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.