Переупорядочить список в Python, чтобы убедиться, что он начинается с проверочных значений - PullRequest
5 голосов
/ 05 марта 2010

Я читаю в последовательных данных с помощью Pyserial, чтобы заполнить список из 17 значений (1 байт каждое) с частотой дискретизации 256 Гц.

Байты, которые я в конечном итоге хочу использовать, находятся в списке с 5 по 8. При отсутствии отброшенных байтов первые два значения потока всегда одинаковы («165», «90»). Однако я получаю довольно много пропущенных значений, и значения в моем списке смещаются, поэтому, когда я читаю 5-8-й байты, они не являются правильными значениями.

Я частично боролся с этим, убедившись, что перед захватом требуемого сегмента первые несколько значений проверяются на соответствие тем, чем они должны быть (т.е. если mylist [0] == 165 & ....). Это грубо, но нормально, поскольку шансы появления этих двух значений рядом друг с другом в списке в другом месте невелики. Проблема в том, что это означает, что как только байты сдвигаются, я теряю множество значений, пока они в конечном итоге не выровняются.

Мой вопрос: какой код я могу использовать для:

a) Принудительно перестроить список, как только будет обнаружено, что он больше не начинается с 165,90. (Элиф ....).

b) Определите, где '165' и '90' находятся (рядом друг с другом) в списке, и извлеките значения, которые мне нужны, относительно их положения (следующее, но одно, далее).

Заранее спасибо

S_S

Только что заметил из связанных вопросов, что я мог бы использовать

mylist.append(mylist.pop(0)) 

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

Ответы [ 3 ]

2 голосов
/ 05 марта 2010

Если я тебя хорошо понял, Предположим, у вас есть такой список:

l = [67, 126, 165, 90, 11, 1, 3, 5, 151, 99, 23]

вы хотите получить: полезно = [3,5,151,99]

Тогда вы можете сделать:

# obtain places where 165 is followed by 90
match = [x for x in xrange(len(l)-1) if l[x]==165 and l[x+1]==90]
# obtain range of useful values
useful = l[match[0]+4:match[0]+8]

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

Manuel

0 голосов
/ 07 марта 2010

Я бы использовал 165 и 90 в качестве значений заголовка, всегда проверяя входящий байт на совпадение. Это решение автоматически выполняет повторную синхронизацию, и оно так же просто, как:

def get_message():
    while True: #Some timeout functionality is useful here ;-)
       message = []
       byte = xxx.get_byte()
       if byte == 165:
          byte = xxx.get_byte()
          if byte == 90:
             xxx.get_byte() #drop it
             xxx.get_byte() #drop it
             message[0] = xxx.get_byte()
             message[1] = xxx.get_byte()
             message[2] = xxx.get_byte()
             message[3] = xxx.get_byte()
             #Break out of loop. We have a message! 
             return message

Если вы разрабатываете обе стороны, вам действительно нужно вставить какую-то контрольную сумму. Если вы просто что-то взламываете, ищите в байтах контрольную сумму. Это, вероятно, уже там.

0 голосов
/ 05 марта 2010

Если я правильно понимаю вашу проблему, у вас есть данные, поступающие непрерывно, 17-байтовыми блоками. Предполагая, что это правильно, как насчет чего-то вроде этого:

while True:    
    mylist.extend(get_more_data())

    # If we're misaligned, skip bytes until we're aligned again
    while mylist and mylist[0] != 165 or mylist[1] != 90:
        mylist.pop(0)

    # If we've skip bytes, we might not have enough data, so get more
    if len(mylist) < 17:
        continue

    # Process one chunk of data and remove it from the list
    process_data(mylist[:17])
    del mylist[:17]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...