Reputation: 9019
I want to be able to input a list of letters (there are only four options for letters in the list), however the list can be up to ten or so items long, for example:
letter_options = ['A', 'B', 'C', 'D']
s = ['B', 'C', 'A', 'C', 'D', 'A']
s = ['C', 'A', 'D', 'C', 'A']
s = ['A', 'B', 'A', 'A', 'D', 'B', 'B']
My question is how would I go about determining if 'B' occurs before a 'D' or an 'A' occurs? If 'B' does not exist in the list, then the code would output 0. If 'B' does occur before an 'A' or 'D', then the code would output 1.
Here is what I have, but it does not work for the case where 'B' does not occur.
letters = ['A', 'A', 'A', 'A']
fkt = []
check = ' '.join(letters).split('B')[0].split()
if letters!=[] and letters[0]=='B':
fkt.append(1)
elif letters!=[] and any(idx in check for idx in ['A', 'D']):
fkt.append(0)
else:
fkt.append(1)
Upvotes: 1
Views: 447
Reputation: 403128
If ['B', 'C', 'A', 'C', 'D', 'A']
is your list and you want to find out whether 'B' precedes 'D', you can convert your list to a string and then use str.find
:
In [141]: l = ''.join(['B', 'C', 'A', 'C', 'D', 'A'])
In [148]: l[:max(0, l.find('D'))].find('A') > -1
Out[148]: True
In general,
In [153]: def foo(l, c1, c2): # is c2 before c1?
...: return l[:max(0, l.find(c1))].find(c2) > -1
...:
In [154]: foo(l, 'B', 'D')
Out[154]: False
In [155]: foo(l, 'D', 'B')
Out[155]: True
str.find
returns -1
, so you can handle no-matches gracefully, since a splice to 0
([:0]
) returns an empty list.
An even simpler alternative is 0 <= l.find('X') < l.find('Y')
as suggested by VPfB:
def foo(l, c1, c2): # is c2 before c1?
return `0 <= l.find('c2') < l.find('c1')`
Upvotes: 2
Reputation: 215117
You could try this method:
def code(lst):
for i in lst:
# loop through the list, if find the element A or D, return 0 and break out of
# the loop
if i in ['A', 'D']:
return 0
# if find B, return 1 and break out of the loop
elif i == 'B':
return 1
# if not find B at all return 0 and break out of the loop
return 0
s1 = ['B', 'C', 'A', 'C', 'D', 'A']
s2 = ['C', 'A', 'D', 'C', 'A']
s3 = ['A', 'B', 'A', 'A', 'D', 'B', 'B']
code(s1)
#1
code(s2)
#0
code(s3)
#0
Or equivalently:
bfirst = 0
for i in lst:
if i in ['A', 'D']:
bfirst = 0
break
elif i == 'B':
bfirst = 1
break
Justification:
Use a simple for loop, and if else to check values, if 'AD' were found firstly, then bfirst is 0 and short circuit (break out of the loop), since there is no need to check other elements anymore; Similarly if 'B' was found firstly, then assign bfirst 1 and short circuit (break out of the loop) for the same reason above; If you have a long list and very few options of letters, this would potentially be very efficient since it only checks a few letters at the beginning of the list without having to thoroughly loop through the list; Under the worst cases (the list is totally made up irrelevant letters), it is still O(N), one pass of the list.
Upvotes: 1