简体   繁体   中英

Python: swap two elements and keep the position of other special characters in a list?

Source data

lst = [1, '^', 3, 5, '!', 'a', '%', 'b', '.', 12, '*']

Desired Result:

[12, '^', 'b', 'a', '!', 5, '%', 3, '.', 1, '*']

Questions:

I want to swap two elements and keep the position of the special characters in a list.

Just swap 1 and 12, 3 and b, 5 and a. (I want to have a better efficiency)

At the same time to traversing the list from the left and right and if the two elements are not special characters, the two elements will be swapped places ?

This approach produces the result that you expect:

import string

lst = [1, '^', 3, 5, '!', 'a', '%', 'b', '.', 12, '*']

# i = Start_Position, j = End_Position
i, j = 0, len(lst)-1

# Traverse while Start_Position < End_Position
while i < j:
   # Swap values at Start_Position and End_Position if not special characters and update indexes
   if str(lst[i]) not in string.punctuation and str(lst[j]) not in string.punctuation:
     lst[i], lst[j] = lst[j], lst[i]
     i += 1
     j -= 1
   # Decrease End_Position as special character found
   elif str(lst[i]) not in string.punctuation and str(lst[j]) in string.punctuation:
     j -= 1
   # Increase Start_Position as special character found
   elif str(lst[i]) in string.punctuation and str(lst[j]) not in string.punctuation:
     i += 1
   # Both values are special characters , update indexes
   else:
     i += 1
     j -= 1

print(lst)
 Input : [1, '^', 3, 5, '!', 'a', '%', 'b', '.', 12, '*'] output: [12, '^', 'b', 'a', '!', 5, '%', 3, '.', 1, '*'] 

Here is my approach. The main idea is to swap a sublist of only non-special characters and then fill the output list preserving the position of the special characters.

Input:

lst = [1, '^', 3, 5, '!', 'a', '%', 'b', '.', 12, '*']

Find the position of special characters:

import string
spec_pos = [idx for idx, el in enumerate(lst) if str(el) in string.punctuation]

Get the non-special values:

to_swap = [el for idx, el in enumerate(lst) if str(el) not in string.punctuation]

Define generic function to swap elements in list, using recursion:

def rec_swap(l):
    if len(l) == 1:
        return l
    if len(l)==2:
        l[0], l[1] = l[1], l[0]
        return l
    else:
        return [l[-1]] + rec_swap(l[1:-1]) + [l[0]]

Swap elements:

swapped = rec_swap(sublist)

Create the output list:

out = []
_ = [out.append(swapped.pop(0)) if idx not in spec_pos else out.append(lst[idx]) for idx, el in enumerate(lst)]

This gives the expected output:

out
Out[60]: [12, '^', 'b', 'a', '!', 5, '%', 3, '.', 1, '*']

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM