Reputation: 881
lst = [1, '^', 3, 5, '!', 'a', '%', 'b', '.', 12, '*']
[12, '^', 'b', 'a', '!', 5, '%', 3, '.', 1, '*']
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)
Upvotes: 0
Views: 305
Reputation: 1947
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, '*']
Upvotes: 1
Reputation: 7476
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, '*']
Upvotes: 1