Python反向跨步切片

发布于 2024-11-04 03:50:35 字数 539 浏览 3 评论 0原文

我的问题的一个具体例子是,“在这个例子中我怎样才能得到‘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],但这会在进程中创建两个字符串对象。我将执行此操作数十亿次,因此每个字符串操作都很昂贵。

我一定错过了一些愚蠢而简单的事情。感谢您的帮助!

A specific example of my question is, "How can I get '3210' in this example?"


>>> 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'

It seems strange that I can write foo[4:0:-1], foo[5:1:-1], etc. and get what I would expect, but there's no way to write the slice so that I get '3210'.

A makeshift way of doing this would be foo[0:4][::-1], but this creates two string objects in the process. I will be performing this operation literally billions of times, so every string operation is expensive.

I must be missing something silly and easy. Thanks for your help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

七七 2024-11-11 03:50:41

给定:

>>> 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

Given:

>>> foo = '0123456'

The desired string 3210 is from index 3rd to the 0-th characters:

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

Here are two generic solutions:

  1. Take the forward slice then reverse it:

    >>> foo[stop_idx:start_idx+1][::-1]
    '3210'
    
  2. Based on this answer, use a negative step and stop 1 element before the first element (plus the stop offset):

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

Comparing execution times, the first version is faster:

>>> 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
无名指的心愿 2024-11-11 03:50:41

除了上述解决方案之外,您还可以执行以下操作:

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

我猜如果 foo 将改变长度,这可能不是最好的解决方案,但如果长度是静态的,它会起作用。

In addition to the above solutions, you can do something like:

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

I guess if foo is going to be changing lengths, this may not be the best solution, but if the length is static it would work.

橘味果▽酱 2024-11-11 03:50:41
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))
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))
ヤ经典坏疍 2024-11-11 03:50:40

如果您正在寻找比扩展切片符号更易于理解的东西:

>>> foo = '0123456'
>>> ''.join(reversed(foo[0:4]))
'3210'

If you're looking for something a little more human-readable than extended slice notation:

>>> foo = '0123456'
>>> ''.join(reversed(foo[0:4]))
'3210'
对你而言 2024-11-11 03:50:40

阅读“技术文档”(此处)后 - 特别是这句话:

如果任一界限为负,则将序列的长度添加到其中。

我决定尝试一下,它起作用了:

>>> 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”的值

After reading the "technical documentation" (here) - specifically the sentence:

If either bound is negative, the sequence’s length is added to it.

I decided to try this, and it worked:

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

So I think the best answer to programmatically determine the "end point" would be to provide a well named helper function that makes it clear that its arguments are always treated like positive offsets, maybe special_slice()

I think the clarity of this 'special' case is extremely important since lots of common and significant use cases depend on the default behavior of negative offsets (i.e. adding the length to them). Personally I frequently use a '-1' end point to mean: stop just before last element.

So, based on your comment:

... algorithm that works somewhat like as follows: foo[i:i-4:-1], and starts with a high 'i' and walks down.

I might make the following:

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]

And then call it for each slice required:

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

The above could easily go in a loop over values of 'i'

溺渁∝ 2024-11-11 03:50:40

您可以使用 s[::-1] 反转整个字符串。但如果你想反转每个固定长度的子串,你可以先提取子串,然后反转整个子串。例如,假设我们需要检查字符串 foo 中每个长度为 3 的子串是否是回文,我们可以这样做:

>>> 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]:
    ...

:将无法处理 i0 的情况,因为您实际上是将 foo[0:3]foo 进行比较[2:-1:-1],相当于 foo[2:n-1:-1],后者是一个空字符串。

第一个解决方案的唯一缺点是它使用了更多的内存,但这没什么大不了的。

You can use s[::-1] to reverse the entire string. But if you want to reverse each substring with some fixed length, you can first extract the substring and then reverse the entire substring. For example, let's assume we need to check whether each substring with length 3 of string foo is a palindrome, we can do it like this:

>>> 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 you want to check if a substring is palindrome like this:

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

you will not be able to handle the case of i being 0, since you are actually comparing foo[0:3] with foo[2:-1:-1], which is equivalent to foo[2:n-1:-1], which in turn is an empty string.

The only drawback of the first solution is that it uses a little more memory but it's no big deal.

2024-11-11 03:50:39

省略切片符号中的结束索引:

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

如果您必须多次执行此操作,请创建一个可以反复使用的切片对象

>>> first_4_items_reversed = slice(3,None,-1)
>>> foo[first_4_items_reversed]
'3210'

Omit the end index in your slice notation:

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

If you have to do this many times, create a slice object that you can use over and over

>>> first_4_items_reversed = slice(3,None,-1)
>>> foo[first_4_items_reversed]
'3210'
喜爱纠缠 2024-11-11 03:50:38

只需排除结束范围索引...

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

具有讽刺意味的是,关于我认为您没有尝试的唯一选项。

Simply exclude the end range index...

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

Ironically, about the only option I think you didn't try.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文