0

Никак не могу сообразить как мне перебрать список, одновременно изменяя некоторые элементы и удаляя следующие за теми, которые изменил. Есть список:

[0x11, 0x03, 0x7D, 0x5E, 0x02, 0xEE]

Это пакет данных, полученный через какой-то интерфейс. Есть стартовый/стоповый байты 0x7E (тут не показаны так как обрезаны уже ранее). Если такой байт встречается внутри пакета, то он экранируется с помощью байта 0x7D, за которым следует исходный байт, но с инвертированным 5-м битом. То есть байт 0x7D кодируется последовательностью 0x7D 0x5D, а байт 0x7E – последовательностью 0x7D 0x5E. То есть я должен из исходного списка получить

[0x11, 0x03, 0x7E, 0x02, 0xEE]

Я написал функцию, но она не работает. Цикл не пропускает следующий байт (

def __unescape(self, bytelist):
    result = []
    for x in range(len(bytelist)):
        if bytelist[x] == self.__EscapeByte:
             # Тут в результрующий список добавляем следующий байт
             # при этом инвертируя пятый бит
            result.append(bytelist[x + 1] ^ 0x20)
            # С помощью увеличения счетчика я хочу чтобы цикл пропустил
            # следующий байт, но почему-то этого не происходит.
            x = x + 1
        else:
            result.append(bytelist[x])
    return result

Причем на C я это написал легко, хотя вообще не спец в C:

void MyClass::_unescape(){
    for (uint8_t i = 0; i < (_packet_len-1); ++i){
        if (_data[i] == _EscapeByte){
            _data[i] = _data[i+1] ^ 0x20;
            _delete_byte(i+1);
        }
    }
}
ddipp
  • 340

1 Answers1

2

Чтобы пропустить значение в списке, можно next() использовать, чтобы итератор продвинуть:

it = iter(bytelist)
result = [next(it) ^ 0x20 if b == ESCAPE_BYTE else b for b in it]

Альтернативно, можно bytes.replace() использовать, если только эти два байта экранируются:

result = bytes(bytelist).replace(b'}^', b'~').replace(b'}]', b'}')
jfs
  • 52,361
  • Отлично! Спасибо большое! – ddipp Feb 27 '18 at 06:56
  • Первый вариант более понятен в моём случае. Но за второй вариант тоже спасибо, сам бы не додумался. – ddipp Feb 27 '18 at 07:19
  • @ddipp: старайтесь не писать Си, используя Питон-синтаксис -- результат будет менее читаем и крайне медленный. Для коллекции байт, в Питоне удобно использовать bytes, bytearray типы и соответствующие методы. В общем случае, можно ещё регулярные выражения применить. – jfs Feb 27 '18 at 08:14
  • Ну я пока не настоящий сварщик. Пишу прикладные вещи для собственного применения, ну а вообще не программист ниразу ). Так что уж пишу как умею. Хотя познавать новое приятно. – ddipp Feb 27 '18 at 19:35