Уведомления

Группа в Telegram: @pythonsu

#1 Дек. 31, 2009 08:58:04

superduck
От:
Зарегистрирован: 2009-11-14
Сообщения: 18
Репутация: +  0  -
Профиль   Отправить e-mail  

текст А и В, если строчка из текста В есть в А - удалить ее

def uniqar(arr):
arr2 = []
for v in arr:
arr2.append(v.strip())
return list(set(arr2))


text = uniqar(open('text.txt', 'r').readlines())
text2 = uniqar(open('text2.txt', 'r').readlines())

text_tmp = text[:]
z = 0

for i in text_tmp:
print str(z) + '/' + str(len(text))
z += 1

if i in text2:
text.remove(i)
del(text_tmp)

ff = open('new_text.txt','w')
ff.write("\n".join(text))
ff.close()
этот код работает крайне медленно.. с текстами от 100к строчек просто жутко медленно.
как можно сделать быстрее?



Офлайн

#2 Дек. 31, 2009 09:13:31

expee
От:
Зарегистрирован: 2009-12-21
Сообщения: 197
Репутация: +  0  -
Профиль   Отправить e-mail  

текст А и В, если строчка из текста В есть в А - удалить ее

Если текст очень большой, то он и будет работать медленно. Можешь расставить принты после некоторых операций и посмотреть, какие блоки сколько выполняются. Кстати, а чем text.replace('string', '') не устроил? Разбить текст на слова можно методом split:

text = open('text.txt').read()
print text.split()
Получишь список слов.



Офлайн

#3 Дек. 31, 2009 09:24:31

expee
От:
Зарегистрирован: 2009-12-21
Сообщения: 197
Репутация: +  0  -
Профиль   Отправить e-mail  

текст А и В, если строчка из текста В есть в А - удалить ее

Вообще можно написать как-то так:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

words = open('haha').read()
intxt = open('huhu').read()

for word in words.split('/n'):
intxt = intxt.replace(word, '')

with open('new', 'w') as n:
n.write(intxt)



Отредактировано (Дек. 31, 2009 11:02:03)

Офлайн

#4 Дек. 31, 2009 09:52:27

superduck
От:
Зарегистрирован: 2009-11-14
Сообщения: 18
Репутация: +  0  -
Профиль   Отправить e-mail  

текст А и В, если строчка из текста В есть в А - удалить ее

expee, твой метод работает гораздо медленнее моего метода с массивами.



Отредактировано (Дек. 31, 2009 09:52:47)

Офлайн

#5 Дек. 31, 2009 10:42:08

PooH
От:
Зарегистрирован: 2006-12-05
Сообщения: 1948
Репутация: +  72  -
Профиль   Отправить e-mail  

текст А и В, если строчка из текста В есть в А - удалить ее

Если я правильно понял задачу: “Отфильтровать из файла А все строки из файла В. Сравнение должно не учитывать пробельные элементы”, то наверное так:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

def normalize(s):
return ''.join(x.strip() for x in s.split())

dt = dict((normalize(x),True) for x in open('1.txt'))
outf = open('3.txt', 'w')
for s in open('2.txt'):
if not normalize(s) in dt:
outf.write(s)



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

Офлайн

#6 Дек. 31, 2009 11:19:37

expee
От:
Зарегистрирован: 2009-12-21
Сообщения: 197
Репутация: +  0  -
Профиль   Отправить e-mail  

текст А и В, если строчка из текста В есть в А - удалить ее

От твоего исходного файла с текстом на выходе функции uniqar остаются лишь уникальные строки. Т.о. у меня есть текст, где встречаются одинаковые строки (например, команды в листингах, но их нет в файле B!) и после обработки на выходе не хватает строк =/ В заголовке ты написал, что нужно удалять только строки, которые етсь в файле B.

Берем файл text, в котором 100к строк. Я для примера взял чередующиеся строки. В файле lines только одна строка, которая встречается в text (поскольку строк 100к и они чередуются, то таких строк в text 50к). После выполнения твоего кода у меня остается лишь одна строка - которых было в text 50к и при этом небыло в lines! Допустим, что это ошибка. Не будем обрабатывать функцией uniqar исходный текст. Вот результат выполнения твоего кода:

real 1m15.745s
user 1m4.240s
sys 0m1.872s
Сразу сознаюсь, что я сначала не понял тебя и написал код для удаления слов из текста B в тексте A. Но я исправился :)
#!/usr/bin/env python
# -*- coding: utf-8 -*-

lines = open('lines').readlines() # файл, из которого нужно брать строки и удалять в intxt
intxt = open('text').read() # файл, из которого нужно удалять строки, которые есть в lines

for line in lines:
intxt = intxt.replace(line, '')

with open('new', 'w') as n:
n.write(intxt.replace('\n\n', '\n'))
Скрипт удаляет все строки, какие есть в lines из text. Выполняем:
expee@localhost:~/dev/python$ time python hehe.py

real 0m0.087s
user 0m0.068s
sys 0m0.008s
Резальтат получаем правильный - в файле 50к строк и нет строк, которые есть в lines.



Отредактировано (Дек. 31, 2009 12:08:29)

Офлайн

#7 Дек. 31, 2009 11:42:11

Ed
От:
Зарегистрирован: 2008-12-13
Сообщения: 1032
Репутация: +  13  -
Профиль   Отправить e-mail  

текст А и В, если строчка из текста В есть в А - удалить ее

Вот мой вариант. На моих данных (2 одинаковых файла с уникальными строками) он работает быстрее исходного и варианта expee. Намного.
Но я допускаю, что на других данных он может быть медленнее.

Кстати, вариант expee у меня работает непозволительно долго. Входной файл в моем случае - это 190K строк длиной около 60 символов.
По-моему replace - не лучшее решение для таких длинных строк.

def uniqar(arr):
return set([v.strip() for v in set(arr)])

text = uniqar(open('text.txt', 'r').readlines())
text2 = uniqar(open('text2.txt', 'r').readlines())

ff = open('new_text.txt','w')
ff.write("\n".join(text.difference(text2)))
ff.close()
PS: Этот вариант сделан на основе кода топикстартера, поэтому он тоже удаляет одинаковые строки.
Я ориентировался на код, а не на слова :)



Отредактировано (Дек. 31, 2009 11:45:25)

Офлайн

#8 Дек. 31, 2009 11:56:17

Ed
От:
Зарегистрирован: 2008-12-13
Сообщения: 1032
Репутация: +  13  -
Профиль   Отправить e-mail  

текст А и В, если строчка из текста В есть в А - удалить ее

И еще. Непонятно, что значит ‘жутко медленно’. Потому как у меня такая статистика для моих данных:
Исходный вариант: 4.7 сек (не сказал бы, что это жутко медленно)
Вариант expee: ждал минут 5, не дождался окончания
Мой вариант: 0.4 сек

Подозреваю, что это еще и от ОС зависит и от мощности компа. У меня линух. комп - P4 2.8 GHz



Офлайн

#9 Дек. 31, 2009 11:58:13

superduck
От:
Зарегистрирован: 2009-11-14
Сообщения: 18
Репутация: +  0  -
Профиль   Отправить e-mail  

текст А и В, если строчка из текста В есть в А - удалить ее

2 Ed
спс, твой вариант работает быстрее вдух остальных предложеных и да, код expee работает очень медленно, не знаю откуда у него такие цифры о времени

450к строк, средняя длина 30символов
код Ed'a
real 0m1.784s
user 0m1.536s
sys 0m0.196s

код PooH'a
real 0m4.558s
user 0m4.312s
sys 0m0.124s


И еще. Непонятно, что значит ‘жутко медленно’.
поставил на его скрипе счётчик в цикле, была скорость около 20строк/сек. т.е даже рядом по скорости не стоит с моим первоночальным кодом..



Отредактировано (Дек. 31, 2009 12:00:20)

Офлайн

#10 Дек. 31, 2009 12:02:39

expee
От:
Зарегистрирован: 2009-12-21
Сообщения: 197
Репутация: +  0  -
Профиль   Отправить e-mail  

текст А и В, если строчка из текста В есть в А - удалить ее

Даже не знаю, как вы считаете :) Взял сейчас файл ~180000 строк по 150 символов. Каждая 3 строка подлежит удалению (есть в lines). Общее количество символов - 27 333 305. Запускаем мой скрипт:

expee@localhost:~/dev/python$ time python hehe.py

real 0m2.232s
user 0m0.164s
sys 0m0.164s
Получаем файл с ~60к строками. Нужна строка удалена.

ps. проц - amd duron 1200.



Отредактировано (Дек. 31, 2009 12:17:49)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version