What is the simplest way to swap each pair of adjoining chars in a string with Python?

前端 未结 19 824
名媛妹妹
名媛妹妹 2020-11-30 06:25

I want to swap each pair of characters in a string. \'2143\' becomes \'1234\', \'badcfe\' becomes \'abcdef\'.

How

相关标签:
19条回答
  • 2020-11-30 07:16

    A bit late to the party, but there is actually a pretty simple way to do this:

    The index sequence you are looking for can be expressed as the sum of two sequences:

     0  1  2  3 ...
    +1 -1 +1 -1 ...
    

    Both are easy to express. The first one is just range(N). A sequence that toggles for each i in that range is i % 2. You can adjust the toggle by scaling and offsetting it:

             i % 2      ->  0  1  0  1 ...
         1 - i % 2      ->  1  0  1  0 ...
    2 * (1 - i % 2)     ->  2  0  2  0 ...
    2 * (1 - i % 2) - 1 -> +1 -1 +1 -1 ...
    

    The entire expression simplifies to i + 1 - 2 * (i % 2), which you can use to join the string almost directly:

    result = ''.join(string[i + 1 - 2 * (i % 2)] for i in range(len(string)))
    

    This will work only for an even-length string, so you can check for overruns using min:

    N = len(string)
    result = ''.join(string[min(i + 1 - 2 * (i % 2), N - 1)] for i in range(N))
    

    Basically a one-liner, doesn't require any iterators beyond a range over the indices, and some very simple integer math.

    0 讨论(0)
  • 2020-11-30 07:17

    Here's one way...

    >>> s = '2134'
    >>> def swap(c, i, j):
    ...  c = list(c)
    ...  c[i], c[j] = c[j], c[i]
    ...  return ''.join(c)
    ...
    >>> swap(s, 0, 1)
    '1234'
    >>>
    
    0 讨论(0)
  • 2020-11-30 07:19

    The usual way to swap two items in Python is:

    a, b = b, a
    

    So it would seem to me that you would just do the same with an extended slice. However, it is slightly complicated because strings aren't mutable; so you have to convert to a list and then back to a string.
    Therefore, I would do the following:

    >>> s = 'badcfe'
    >>> t = list(s)
    >>> t[::2], t[1::2] = t[1::2], t[::2]
    >>> ''.join(t)
    'abcdef'
    
    0 讨论(0)
  • 2020-11-30 07:19

    There is no need to make a list. The following works for even-length strings:

    r = ''
    for in in range(0, len(s), 2) :
      r += s[i + 1] + s[i]
    s = r
    
    0 讨论(0)
  • 2020-11-30 07:19
    >>> import ctypes
    >>> s = 'abcdef'
    >>> mutable = ctypes.create_string_buffer(s)
    >>> for i in range(0,len(s),2):
    >>>     mutable[i], mutable[i+1] = mutable[i+1], mutable[i]
    >>> s = mutable.value
    >>> print s
    badcfe
    
    0 讨论(0)
  • 2020-11-30 07:20

    A more general answer... you can do any single pairwise swap with tuples or strings using this approach:

    # item can be a string or tuple and swap can be a list or tuple of two
    # indices to swap
    def swap_items_by_copy(item, swap):
       s0 = min(swap)
       s1 = max(swap)
       if isinstance(item,str):
            return item[:s0]+item[s1]+item[s0+1:s1]+item[s0]+item[s1+1:]
       elif isinstance(item,tuple):
            return item[:s0]+(item[s1],)+item[s0+1:s1]+(item[s0],)+item[s1+1:]
       else:
            raise ValueError("Type not supported")
    

    Then you can invoke it like this:

    >>> swap_items_by_copy((1,2,3,4,5,6),(1,2))
    (1, 3, 2, 4, 5, 6)
    >>> swap_items_by_copy("hello",(1,2))
    'hlelo'
    >>> 
    

    Thankfully python gives empty strings or tuples for the cases where the indices refer to non existent slices.

    0 讨论(0)
提交回复
热议问题