#python #string #replace #find
#python #строка #заменить #Найти
Вопрос:
Мне кажется, что это просто, но я просто недостаточно знаю о python, чтобы сделать это правильно.
У меня есть два файла:
- Файл со строками, в которых указан идентификационный номер и используется ли этот идентификатор. Формат ‘id, isUsed’.
- Файл с правилами, содержащий одно правило для каждого идентификатора.
Итак, что я хочу сделать, это проанализировать файл с парами id-used, а затем на основе этой информации я найду соответствующее правило во втором файле, а затем прокомментирую или отменю комментарий к правилу в зависимости от того, используется ли это правило.
Есть ли простой способ выполнить поиск во втором файле для правила, которое я ищу, вместо того, чтобы каждый раз искать его построчно? Кроме того, должен ли я переписывать файл каждый раз, когда я изменяю файл.
Вот что у меня есть на данный момент, я действительно не знаю, какой наилучший способ реализовать modifyRulesFile():
def editRulesFile(pairFile, ruleFile):
pairFd = open(pairFile, 'r')
ruleFd = open(ruleFile, 'rw')
for line in pairFd.readLine():
id,isUsed = line.split(',')
modifyRulesFile(ruleFd, id, isUsed)
def modifyRulesFile(fd, id, isUsed):
for line in fd.readLine():
# Find line with id in it and add a comment or remove comment based on isUsed
Ответ №1:
Я предлагаю вам прочитать файл правил в словаре (id -> правило). Затем, по мере чтения конфигурационного файла, запишите соответствующее правило (включая комментарий, если вам нужно).
некоторый псевдокод:
rules = {}
for id, rule in read_rules_file():
rules[id] = rule
for id, isUsed in read_pairs_file():
if isUsed:
write_rule(id, rules[id])
else:
write_commented_rule(id, rules[id])
Таким образом, вы пройдете через каждый файл только один раз. Если файл правил становится очень длинным, возможно, вам не хватает памяти, но обычно для этого требуется много времени!
Вы можете использовать генераторы, чтобы избежать хранения всех пар в памяти одновременно:
def read_pairs_file():
pairFd = open(pairFile, 'r')
for line in pairFd.readLines():
id, isUsed = line.split(',')
yield (id, isUsed)
pairFd.Close()
Комментарии:
1. 1: Не связывайтесь с вводом-выводом на уровне файла для чего-то такого крошечного. Просто поместите все это в память и работайте с объектами как можно проще и непосредственнее.
2. Размер файла правил составляет около 14 МБ, это слишком большой размер, чтобы прочитать все это в памяти, или это должно иметь значение? Я только что увидел ваш комментарий о генераторах, большое спасибо!
3. Нет. Вы можете легко использовать 14 МБ. Даже не думайте об этом
![]()
4. Кроме того, вы, вероятно, могли бы переключить логику здесь и сохранить пары в словаре (id -> isUsed) и выполнить цикл по правилам. Запишите выходные данные во временный файл и, когда закончите, замените исходный файл временным.
5. @Кевин С. «14 МБ»? Сколько оперативной памяти у вашего компьютера? Это где-нибудь около 14 МБ? Он в 100 раз больше? (1,4 ГБ) или это даже больше, чем это?
Ответ №2:
Я не знаю, почему я не подумал об этом раньше, но есть другой способ сделать это.
Сначала вы читаете, какие правила следует использовать (или не использовать) в памяти, я сохранил это в словаре.
def readRulesIntoMemory(fileName):
rules = {}
# Open csv file with rule id, isUsed pairs
fd = open(fileName, 'r')
if fd:
for line in fd.readlines():
id,isUsed = line.split(',')
rules[id] = isUsed
Затем, читая список текущих правил в другом файле, запишите свои изменения во временный файл.
def createTemporaryRulesFile(temporaryFileName, rulesFileName, rules):
# Open current rules file for reading.
rulesFd = open(rulesFileName, 'r')
if not rulesFd:
return False
# Open temporary file for writing
tempFd = open(temporaryFileName, 'w')
if not tempFd:
return False
# Iterate through each current rule.
for line in rulesFd.readlines():
id = getIdFromLine(line)
isCommented = True # Default to commenting out rule
# If rule's id is was in csv file from earlier, save whether we comment
# the line or not.
if id in rules:
isCommented = rules[id]
if isCommented:
writeCommentedLine(tempFd, line)
else:
writeUncommentedLine(tempFd, line)
return True
Теперь мы можем скопировать новый временный файл поверх исходного, если захотим.