Как мне сделать то, что strtok () делает в C, в Python? - PullRequest
8 голосов
/ 19 января 2009

Я изучаю Python и пытаюсь найти эффективный способ маркировки строки чисел, разделенных запятыми, в список. Хорошо сформированные случаи работают, как я ожидаю, но менее хорошо сформированные случаи не так много.

Если у меня есть это:

A = '1,2,3,4'
B = [int(x) for x in A.split(',')]

B results in [1, 2, 3, 4]

это то, что я ожидаю, но если строка более похожа на

A = '1,,2,3,4,'

если я использую то же самое выражение списка для B, что и выше, я получаю исключение. Я думаю, что понимаю, почему (потому что некоторые строковые значения "x" не являются целыми числами), но я думаю, что был бы способ разобрать это все еще довольно элегантно, так что токенизация строки a работает немного более прямо как strtok (A, ", \ n \ t") сделал бы, когда вызывается итеративно в C.

Чтобы было ясно, о чем я спрашиваю; Я ищу элегантный / эффективный / типичный способ для Python, чтобы иметь все следующие примеры случаев строк:

A='1,,2,3,\n,4,\n'
A='1,2,3,4'
A=',1,2,3,4,\t\n'
A='\n\t,1,2,3,,4\n'

возврат с тем же списком:

B=[1,2,3,4]

через какое-то компактное выражение.

Ответы [ 9 ]

28 голосов
/ 19 января 2009

Как насчет этого:

A = '1, 2,,3,4  '
B = [int(x) for x in A.split(',') if x.strip()]

x.strip () удаляет пробел из строки, что делает его пустым, если строка является пробелом. Пустая строка имеет значение «false» в логическом контексте, поэтому она фильтруется частью понимания списка if.

4 голосов
/ 19 января 2009

Ммм, функциональное совершенство (с добавленным битом выражения генератора):

a = "1,2,,3,4,"
print map(int, filter(None, (i.strip() for i in a.split(','))))

Для полной функциональной радости:

import string
a = "1,2,,3,4,"
print map(int, filter(None, map(string.strip, a.split(','))))
4 голосов
/ 19 января 2009

Как правило, я стараюсь избегать регулярных выражений, но если вы хотите разделить на несколько разных вещей, они работают. Попробуйте это:

import re
result = [int(x) for x in filter(None, re.split('[,\n,\t]', A))]
2 голосов
/ 16 октября 2016

Ради полноты я отвечу на этот семилетний вопрос: Программа на C, которая использует strtok:

int main()
{
    char myLine[]="This is;a-line,with pieces";
    char *p;
    for(p=strtok(myLine, " ;-,"); p != NULL; p=strtok(NULL, " ;-,"))
    {
        printf("piece=%s\n", p);
    }
}

может быть выполнено в python с re.split как:

import re
myLine="This is;a-line,with pieces"
for p in re.split("[ ;\-,]",myLine):
    print("piece="+p)
1 голос
/ 19 января 2009

Зачем принимать низшие заменители, которые не могут испортить ваш переводчик? С помощью ctypes вы можете просто назвать настоящую вещь! : -)

# strtok in Python
from ctypes import c_char_p, cdll

try: libc = cdll.LoadLibrary('libc.so.6')
except WindowsError:
     libc = cdll.LoadLibrary('msvcrt.dll')

libc.strtok.restype = c_char_p
dat = c_char_p("1,,2,3,4")
sep = c_char_p(",\n\t")
result = [libc.strtok(dat, sep)] + list(iter(lambda: libc.strtok(None, sep), None))
print(result)
1 голос
/ 19 января 2009

Как насчет этого?

>>> a = "1,2,,3,4,"
>>> map(int,filter(None,a.split(",")))
[1, 2, 3, 4]
Фильтр

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

РЕДАКТИРОВАТЬ: только что проверил это с вышеупомянутыми опубликованными версиями, и, кажется, это значительно быстрее, 15% или около того по сравнению с strip () один и более чем в два раза быстрее, чем isdigit () один

1 голос
/ 19 января 2009

Это сработает и никогда не вызовет исключения, если все числа являются целыми числами. Вызов isdigit() имеет значение false, если в строке есть десятичная точка.

>>> nums = ['1,,2,3,\n,4\n', '1,2,3,4', ',1,2,3,4,\t\n', '\n\t,1,2,3,,4\n']
>>> for n in nums:
...     [ int(i.strip()) for i in n if i.strip() and i.strip().isdigit() ]
... 
[1, 2, 3, 4]
[1, 2, 3, 4]
[1, 2, 3, 4]
[1, 2, 3, 4]
0 голосов
/ 19 января 2009

Почему бы просто не обернуть в попытке, кроме блока, который ловит что-то не целое число?

0 голосов
/ 19 января 2009

Я думаю, что регулярные выражения - это то, что нужно: http://docs.python.org/library/re.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...