#python #list
#python #Список
Вопрос:
У меня есть список, который выглядит следующим образом:
['G1X0.000Y3.000', 'G2X2.000Y3.000I1.000J2.291', 'G1X2.000Y-0.000', 'G2X0.000Y0.000I-1.000J-2.291']
Форматирование таково, что если числовое содержимое после X, Y, I или J положительное, знак отсутствует, но если они отрицательные, то включается знак — . Я пытаюсь перебрать этот список и в основном добавить знак , если в начале числового содержимого нет знака. Результат должен выглядеть следующим образом:
['G1X 0.000Y 3.000', 'G2X 2.000Y 3.000I 1.000J 2.291', 'G1X 2.000Y-0.000', 'G2X 0.000Y 0.000I-1.000J-2.291']
Я пытаюсь использовать понимание списка, чтобы сделать это следующим образом:
#Make sure that X, Y, I and J start with or -
for count,i in enumerate(fileContents):
if 'G' in i:
indexOfI = i.index("X")
if(i[indexOfI 1]!="-"):
print(i[:indexOfI 1] " " i[indexOfI 1:])
fileContents[count] = i[:indexOfI 1] " " i[indexOfI 1:]
indexOfY = i.index("Y")
if(i[indexOfY 1]!="-"):
fileContents[count] = i[:indexOfY 1] " " i[indexOfY 1:]
if "G2" in i:
indexOfI = i.index("I")
if(i[indexOfI 1]!="-"):
fileContents[count] = i[:indexOfI 1] " " i[indexOfI 1:]
indexOfJ = i.index("J")
if(i[indexOfJ 1]!="-"):
fileContents[count] = i[:indexOfJ 1] " " i[indexOfJ 1:]
оператор print(i[:indexOfI 1] " " i[indexOfI 1:])
выдает в консоли вывод:
G1X 0.000Y3.000
G2X 2.000Y3.000I1.000J2.291
G1X 2.000Y-0.000
G2X 0.000Y0.000I-1.000J-2.291
Который показывает мне, что это выполняет то, что я хочу, однако, если я печатаю fileContents
после этой функции, в списке нет изменений. Другими словами, следующая строка кода не заменяет элемент списка в каждой позиции, как я ожидаю:
fileContents[count] = i[:indexOfI 1] " " i[indexOfI 1:]
Почему это не работает, когда я могу сделать следующее, и он правильно обновляет список?
#Format each command to a 32 byte string
for i, s in enumerate(fileContents):
fileContents[i] =s.ljust(32,'#')
редактировать: изначально я озаглавил сообщение «Почему использование такого понимания списка не заменяет каждый элемент в списке?». Пользователи любезно указали, что это не имеет ничего общего с пониманием списка. Прошу прощения, я думал, что этот формат x in list
предназначен для понимания списка.
Комментарии:
1. в вашем коде нет понимания списка
2. Не знаю, почему вы ссылаетесь на понимание списка в названии вашего вопроса, потому что вы, похоже, не используете ни один из них. Но не волнуйтесь, циклы for в порядке.
3. Что такое
s[indexOfI 1]
?4. Почему бы не изучить, а затем использовать регулярные выражения? Синтаксический анализ, основанный на
.index()
, обычно находится на хрупкой стороне.5. Вы видите четыре повторяющихся бита кода — они должны быть в функции, которую вы вызываете с символом для проверки, тогда вам нужно написать и поддерживать ее только один раз
Ответ №1:
если я печатаю
fileContents
после этой функции, в списке нет изменений.
На самом деле, есть изменения, но добавляется не более одного
(последнего).
Это потому, что вы не применяете одно и то же изменение к i
, что означает, что следующие if
блоки будут копировать часть из i
back в, в fileContents[count]
которой не было предыдущего изменения.
Быстрое решение — убедиться, что вы также применяете изменение к i
. Что-то вроде:
fileContents[count] = i = i[:indexOfI 1] " " i[indexOfI 1:]
# ^^^^
Вы можете выполнить эту задачу с пониманием списка, используя re.sub
:
import re
fileContents = [re.sub(r"([XYIJ])(?=d)", r"1 ", line) for line in fileContents]
Это будет соответствовать любому X, Y, I или J, за которым следует цифра. В этом случае между ними вставляется плюс. Если вам нужны более строгие правила сопоставления, где строка должна начинаться с «G», … и т.д., Тогда регулярное выражение станет более сложным.
Комментарии:
1. Спасибо за это быстрое исправление! Из интереса, есть ли более питонический способ сделать это?
2. К моему ответу добавлено решение с пониманием списка.
Ответ №2:
В цикле
for i, s in enumerate(fileContents):
вы перебираете fileContents
список, который хотите изменить в том же цикле. Это всегда опасно.
Выполните итерацию по копии этого списка, который вы можете просто создать, добавив к нему [:]:
for i, s in enumerate(fileContents[:]):
Ответ №3:
Вы можете просто добавить
после любого из этих символов, а затем заменить back -
(для любого) на -
:
def my_replace(item):
for char in 'XYIJ':
item = item.replace(char, f'{char} ')
return item.replace(' -', '-')
spam = ['G1X0.000Y3.000', 'G2X2.000Y3.000I1.000J2.291',
'G1X2.000Y-0.000', 'G2X0.000Y0.000I-1.000J-2.291']
eggs = [my_replace(item) for item in spam] # now, this is list comprehension
print(eggs)
вывод
['G1X 0.000Y 3.000', 'G2X 2.000Y 3.000I 1.000J 2.291', 'G1X 2.000Y-0.000', 'G2X 0.000Y 0.000I-1.000J-2.291']