问题
I have a list of values like this:
vect_i = ['a','X','c','g','X','t','o','X','q','w','e','r','t','y','u','i','o','p','Y','x','c','v','b','Y','b','n','m','Y','q','a','d','Y',]
my goal would be to select in a smart way only the values that are within the last X and the first Y (notice capital X and Y).
The output should be something like this:
vect_f = ['q','w','e','r','t','y','u','i','o','p','Y','x','c','v','b']
Is there a smart way to do this selection. I have figured out a way to do it by counting the number of Xs and Ys and collect only what is comprehended between the corresponding indexes but this is very bad coding in my opinion.
Could you suggest me a nice way to achieve my goal?
回答1:
One line:
vect_i[(vect_i.reverse(), len(vect_i) - vect_i.index('X'), vect_i.reverse())[1] : vect_i.index('Y')]
or
vect_i[len(vect_i) - vect_i[::-1].index('X') : vect_i.index('Y')]
回答2:
vect_i[len(vect_i)-vect_i[::-1].index('X'): vect_i.index('Y')]
retrurn the desired output
回答3:
Most of the other answers are either calling index
multiple times, or mutating and/or copying the list in some form. I think you can simply use enumerate
and get the slice indices for the desired positions in O(n):
ix = iy = 0
for i, v in enumerate(vect_i):
if v == 'X':
ix = i
elif v == 'Y':
iy = i
break
print(vect_i[ix+1:iy])
# ['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p']
回答4:
that would be my way:
indexOfLastX = len(vect_i) - 1 - vect_i[::-1].index("X")
indexOfFirstY = vect_i.index("Y")
print(vect_i[indexOfLastX + 1:indexOfFirstY])
resulting in "['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p']". In your example result is a "Y", what is suprising, when you want to stop at the first "Y"...
回答5:
Something like this?
def sliceBetween(arr, ch1, ch2):
if ch1 not in arr or ch2 not in arr:
return []
left = len(arr) - arr[::-1].index(ch1) - 1
right = arr.index(ch2)
if left >= right:
return []
return [left+1:right]
回答6:
Just try with this code:
endIndex = vect1.index('Y')
dum = ''.join(vect1)
startIndex = dum.rfind('X')
print vect1[startIndex+1:endIndex]
回答7:
get all diffs between every X > Y, "last X and the first Y" are the first item in vect_f
vect_f = []
x = [x for x,o in enumerate(reversed(vect_i)) if o == "X"]
for diff in x:
sub_vect_f = []
for sub_diff in range(len(vect_i)- diff, len(vect_i)):
val = vect_i[sub_diff]
if val!="Y":
sub_vect_f.append(val)
else:
vect_f.append(sub_vect_f)
break
for vect in vect_f:
print (vect)
['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p']
['t', 'o', 'X', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p']
['c', 'g', 'X', 't', 'o', 'X', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p']
回答8:
Bisect search in temporary sorted list will be fast (O(2 log n)). But there is disadvantages - you need to create additional sorted list with original indexes. You can use it if selection need to be made more than once with different chars and original list is not very big:
from bisect import bisect_left
sorted_list_with_idx = sorted((v,i) for i,v in enumerate(vect_i))
# -1 because we need to insert before index of first 'Y' in list
sorted_y_idx = bisect_left(sorted_list_with_idx, ('Y', -1))
# len(vect_i) used as max index to insert to right of last 'X'
# -1 because last 'X' will be before inserted 'new X'
sorted_x_idx = bisect_left(sorted_list_with_idx, ('X', len(vect_i))) - 1
y_idx = sorted_list_with_idx[sorted_y_idx][1]
x_idx = sorted_list_with_idx[sorted_x_idx][1]
>>> sorted_list_with_idx
[('X', 1), ('X', 4), ('X', 7), ('Y', 18), ('Y', 23), ('Y', 27), ('Y', 31),
('a', 0), ('a', 29), ('b', 22), ('b', 24), ('c', 2), ('c', 20), ('d', 30),
('e', 10), ('g', 3), ('i', 15), ('m', 26), ('n', 25), ('o', 6), ('o', 16),
('p', 17), ('q', 8), ('q', 28), ('r', 11), ('t', 5), ('t', 12), ('u', 14),
('v', 21), ('w', 9), ('x', 19), ('y', 13)]
>>> y_idx
18
>>> x_idx
7
>>> vect_i[x_idx+1:y_idx]
['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p']
来源:https://stackoverflow.com/questions/40630340/how-to-select-a-chunk-of-list-between-two-values-in-python