Python обратный шаг нарезки - PullRequest
28 голосов
/ 27 апреля 2011

Конкретный пример моего вопроса: «Как я могу получить« 3210 »в этом примере?»


>>> foo = '0123456'
>>> foo[0:4]
'0123'
>>> foo[::-1]
'6543210'
>>> foo[4:0:-1] # I was shooting for '3210' but made a fencepost error, that's fine, but...
'4321'
>>> foo[3:-1:-1] # How can I get '3210'?
''
>>> foo[3:0:-1]
'321'

Кажется странным, что я могу написать foo [4: 0: -1],foo [5: 1: -1] и т. д. и получите то, что я ожидал, но нет способа написать срез, чтобы я получил '3210'.

Временным способом было бы foo[0: 4] [:: - 1], но это создает два строковых объекта в процессе.Я буду выполнять эту операцию буквально миллиарды раз, поэтому каждая строковая операция стоит дорого.

Я, должно быть, упускаю что-то глупое и легкое.Спасибо за вашу помощь!

Ответы [ 8 ]

37 голосов
/ 27 апреля 2011

Просто исключите индекс конечного диапазона ...

>>> foo[3::-1]
'3210'

По иронии судьбы, об единственном варианте, я думаю, вы не пробовали.

8 голосов
/ 27 апреля 2011

Если вы ищете что-то более понятное человеку, чем расширенная запись среза:

>>> foo = '0123456'
>>> ''.join(reversed(foo[0:4]))
'3210'
6 голосов
/ 27 апреля 2011

Не указывайте конечный индекс в нотации среза:

>>> foo = '0123456'
>>> foo[3::-1]
'3210'

Если вам приходится делать это много раз, создайте объект среза, который можно использовать снова и снова

>>> i = slice(3,None,-1)
>>> foo[i]
'3210'
3 голосов
/ 21 апреля 2016

После прочтения «технической документации» ( здесь ), а именно предложения:

Если любая из границ отрицательна, к ней добавляется длина последовательности.

Я решил попробовать это, и это сработало:

>>> foo = '0123456'
>>> foo[3:-1-len(foo):-1]
'3210'
>>>

Так что я думаю, что лучшим ответом для программного определения «конечной точки» было бы предоставление хорошо названной вспомогательной функции, которая делаетЯсно, что его аргументы всегда обрабатываются как положительные смещения, может быть special_slice()

Я думаю, что ясность этого «особого» случая чрезвычайно важна, так как множество общих и значимых вариантов использования зависит от поведения по умолчанию отрицательногосмещения (т.е. добавление длины к ним).Лично я часто использую конечную точку «-1» для обозначения: остановка перед последним элементом.

Итак, основываясь на вашем комментарии:

... алгоритм, который работает примерно такследующим образом: foo [i: i-4: -1], и начинается с высокого 'i' и идет вниз.

Я мог бы сделать следующее:

def slice_by_len(data, start, length, step=1):
    end = start + length if step > 0 else start - length
    if end < 0:
        # Fix the negative offset to get what we really want
        end -= len(data)
    return data[start:end:step]

И затем вызывать его для каждого необходимого среза:

foo_part = slice_by_len(foo, i, 4, -1)

Вышеуказанное может легко зацикливаться на значениях 'i'

3 голосов
/ 12 мая 2015

Вы можете использовать s[::-1], чтобы полностью изменить строку. Но если вы хотите перевернуть каждую подстроку с некоторой фиксированной длиной, вы можете сначала извлечь подстроку, а затем перевернуть всю подстроку. Например, давайте предположим, что нам нужно проверить, является ли каждая подстрока длиной 3 строки foo палиндромом, мы можем сделать это так:

>>> foo = '0102030'
>>> for i in range(len(foo)-3):
...     if foo[i:i+3] == foo[i:i+3][::-1]:
...         print(foo[i:i+3], 'is a palindrome')
...     else:
...         print(foo[i:i+3], 'is not a palindrome')
...
010 is a palindrome
102 is not a palindrome
020 is a palindrome
203 is not a palindrome
030 is a palindrome

Если вы хотите проверить, является ли подстрока палиндромом, как это:

if foo[i:i+3] == foo[i+2:i-1:-1]:
    ...

вы не сможете обработать случай, когда i равен 0, поскольку вы фактически сравниваете foo[0:3] с foo[2:-1:-1], что эквивалентно foo[2:n-1:-1], что, в свою очередь, является пустой строкой.

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

1 голос
/ 15 сентября 2013

В дополнение к вышеупомянутым решениям вы можете сделать что-то вроде:

foo = '0123456'
foo[-4::-1]

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

0 голосов
/ 14 апреля 2018

Дано:

>>> foo = '0123456'

Желаемая строка 3210 от индекса 3-го до 0-го символа:

>>> stop_idx=0
>>> start_idx=3

Вот два общих решения:

  1. Возьмите передний срез, затем переверните его:

    >>> foo[stop_idx:start_idx+1][::-1]
    '3210'
    
  2. На основании этого ответа используйте отрицательный шаг и остановите 1 элемент перед первым элементом (плюс смещение останова):

    >>> foo[start_idx:stop_idx-len(foo)-1:-1]
    '3210'
    
    >>> a[start_idx:stop_idx-len(a)-1:-1]
    [2, 1]
    

Сравнивая время выполнения, первая версия быстрее:

>>> timeit.timeit('foo[stop_idx:start_idx+1][::-1]', setup='foo="012345"; stop_idx=0; start_idx=3', number=10_000_000)
1.7157553750148509
>>> timeit.timeit('foo[start_idx:stop_idx-len(foo)-1:-1]', setup='foo="012345"; stop_idx=0; start_idx=3', number=10_000_000)
1.9317215870250948
0 голосов
/ 15 декабря 2017
s="this is my world"
pattern=re.findall(r'\S+',s)
a=[]
for i in range(len(pattern)):
    a.append((pattern[i][::-1]))
print (a)
print (" ".join(a))
...