Rita Sue and Bob too

M

M. Clift

Hi All,

Can someone help. I promise I've looked how to do this but can't find a
way...

Ok, to find one name is easy

if 'Bob' in list:
print "They were found"
else:
print "They are not in list"

But, how to I find a sequence in a list of unknown size? i.e. this sequence
in list of other names and replace it with three others?

'Rita','Sue','Bob'

This is almost a nightly occurrence (my posting questions), but I am
learning : )
 
P

Peter Hansen

M. Clift said:
Hi All,

Can someone help. I promise I've looked how to do this but can't find a
way...

Ok, to find one name is easy

if 'Bob' in list:
print "They were found"
else:
print "They are not in list"

But, how to I find a sequence in a list of unknown size? i.e. this sequence
in list of other names and replace it with three others?

'Rita','Sue','Bob'

This is almost a nightly occurrence (my posting questions), but I am
learning : )

My first thought would be to scan the list for the first element
'Rita', and when you find it, take out a slice that is the
same size as the sequence you have there (use len() of course)
and compare the two. If they don't match, move on. The scanning
and "moving on" part would certainly best be done using .index()
and note that that function can take a second parameter which
specifies the starting index, so you can do a progressive search
efficiently. The actual code is left as an exercise to the
reader. ;-)

-Peter
 
J

Jeremy Jones

M. Clift said:
Hi All,

Can someone help. I promise I've looked how to do this but can't find a
way...

Ok, to find one name is easy

if 'Bob' in list:
print "They were found"
else:
print "They are not in list"

But, how to I find a sequence in a list of unknown size? i.e. this sequence
in list of other names and replace it with three others?

'Rita','Sue','Bob'

This is almost a nightly occurrence (my posting questions), but I am
learning : )
I'm sure someone else can come up with something more elegant, but
here's a way you could do it:
>>> names ['larry', 'curly', 'moe', 'shimp', 'rita', 'sue', 'bob', 'billy', 'scott']
>>> for idx in range(len(names)):
.... if names[idx:idx + 3] == ['sue', 'bob', 'billy']:
.... print "found 'em at element", idx
.... break
....
found 'em at element 5
Notice, this:
>>> ['sue', 'bob', 'billy'] in names False
>>>
returns false. The reason is, I think, because the set ['sue', 'bob',
'billy'] is not really a subset of ['larry', 'curly', 'moe', 'shimp',
'rita', 'sue', 'bob', 'billy', 'scott'], even though the three names
appear sequentially in both lists. But, this:
[['sue', 'bob', 'billy'], ['larry', 'curly', 'moe', 'shimp', 'rita',
'sue', 'bob', 'billy', 'scott']]
>>> ['sue', 'bob', 'billy'] in names2 True
>>>
does "work" for the same reason that it doesn't work in the first
example. The list ['sue', 'bob', 'billy'] itself is part of the larger
list, names2.

HTH,

Jeremy Jones
 
P

Paul Rubin

M. Clift said:
But, how to I find a sequence in a list of unknown size? i.e. this sequence
in list of other names and replace it with three others?

'Rita','Sue','Bob'

This is almost a nightly occurrence (my posting questions), but I am
learning : )

You have to scan through the list and look for that sequence, e.g.

for i in xrange(len(mylist) - 2):
if mylist[i:i+3] == ['Rita','Sue','Bob']:
print 'They were found'
break

There are fancier and more efficient ways to scan the list, but this
is the basic idea.
 
E

Eugene Oden

M. Clift said:
Hi All,

Can someone help. I promise I've looked how to do this but can't find a
way...

Ok, to find one name is easy

if 'Bob' in list:
print "They were found"
else:
print "They are not in list"

But, how to I find a sequence in a list of unknown size? i.e. this
sequence in list of other names and replace it with three others?

'Rita','Sue','Bob'

This is almost a nightly occurrence (my posting questions), but I am
learning : )

here's my stab at it:

def findSequence(seq, search):
"""returns the index where search can be found in seq where search and
seq are both sequences.
"""
searchLength = len(search)

for i in range(len(seq)-searchLength+1):
compare = seq[i:i+searchLength+1]

if search == seq[i:i+searchLength]:
return i

raise ValueError, 'sequence %s is not in list' % str(search)

someList = ['Joe', 'Rita', 'Sue', 'Bob', 'Peter']
searchList = ['Rita', 'Sue', 'Bob']

i = findSequence(someList, searchList)
someList[i:i+len(searchList)] = ['Paul', 'John', 'James']
# someList is now ['Joe', 'Paul', 'John', 'James', 'Peter']

findSequence(someList, searchList) # raises ValueError
 
J

Jeffrey Froman

M. Clift said:
But, how to I find a sequence in a list of unknown size? i.e. this
sequence in list of other names and replace it with three others?

How about a generator?

def slice(apple, worm, new_worm):
while apple:
if worm == apple[:len(worm)]:
apple = apple[len(worm):]
yield new_worm
else:
yield [apple.pop(0)]

Jeffrey
 
J

Jeffrey Froman

Jeffrey said:
How about a generator?

Sorry, bad paste on my previous reply. The generator example should look
like:

def replace_in_list(apple, worm, new_worm):
while apple:
if worm == apple[:len(worm)]:
apple = apple[len(worm):]
for w in new_worm:
yield w
else:
yield apple.pop(0)
 
M

Michael J. Fromberger

"M. Clift said:
Hi All,

Can someone help. I promise I've looked how to do this but can't find a
way...

Ok, to find one name is easy

if 'Bob' in list:
print "They were found"
else:
print "They are not in list"

But, how to I find a sequence in a list of unknown size? i.e. this sequence
in list of other names and replace it with three others?

'Rita','Sue','Bob'

This is almost a nightly occurrence (my posting questions), but I am
learning : )

You've gotten several other answers, but I'd like to propose yet another
one:

def replace_sublist(L, S, T):
"""Replace each sublist of L equal to S with T. Also returns the
resulting list."""

assert(len(S) == len(T))

for p in [ x for x in xrange(len(L))
if L[x] == S[0] and L[x : x + len(S)] == S ]:
L[p : p + len(S)] = T

return L

In short, the list comprehension gives all the offsets in L where a copy
of S can be found as a sublist. Now, if it happens that some of these
positions overlap (e.g., L = [ 1, 1, 1 ] and S = [ 1, 1 ]), then the
results will be strange. But as long as your matches do not overlap,
this should work well.

-M
 
M

M. Clift

If I wasn't happy enough already with the examples/ideas you've all shown
me, how about searching as previously, but where the middle name could be
anything. i.e. 'Rita', 'anyname','Bob'

M
 
L

Lo?c Mah?

Hello

You can do it with list List Comprehensions:

BigList = ['Jean', 'Eric', 'Remy', 'Anne', 'Denis', 'Alain', 'Armel',
'Louis']
SmallList = ['Eric', 'Denis', 'Georges', 'Jean']

if ( [x for x in SmallList if x in BigList] == SmallList ):
print "They were found"
else:
print "They are not in list"


[x for x in SmallList if x in BigList] evaluates to a list with common
elements of SmallList and BigList


Loïc
 
P

Peter Hansen

M. Clift said:
If I wasn't happy enough already with the examples/ideas you've all shown
me, how about searching as previously, but where the middle name could be
anything. i.e. 'Rita', 'anyname','Bob'

How about this? (may need more test cases, and then perhaps fixes):


class Anything:
'''wildcard: matches anything'''
pass


def sliceCompare(left, right):
'''compare left and right, returning True if equal (allows wildcard)'''
if len(left) != len(right):
return False
else:
for l, r in zip(left, right):
if Anything in [l, r]:
pass
elif l != r:
return False
else:
return True


def sliceIndex(seq, sub, start=0):
'''search starting at 'start' for sub in seq, return index of match
or -1'''
try:
i = seq.index(sub[0], start)
while i >= 0:
if sliceCompare(seq[i:i+len(sub)], sub):
return i
i = seq.index(sub[0], i+1)
except ValueError:
pass
return -1



def test():
case1 = ['Rita', 'Sue', 'Bob']
alist = 'Rita Mary Jane Bob Sue Carl Hans Rita Bob Sue'.split()
assert sliceIndex([], case1) == -1
assert sliceIndex(alist, case1) == -1

alist = 'Rita Mary Jane Bob Rita Carl Bob Hans Rita Sue Bob Sue
Rita Sue Bob'.split()
assert sliceIndex(alist, case1) == 8
assert sliceIndex(alist, case1, 9) == 12
assert sliceIndex(alist, case1, 13) == -1

case2 = ['Rita', Anything, 'Bob']
assert sliceIndex(alist, case2) == 4
assert sliceIndex(alist, case2, 5) == 8
assert sliceIndex(alist, case2, 9) == 12


if __name__ == '__main__':
test()
 
P

Peter Otten

Peter said:
How about this? (may need more test cases, and then perhaps fixes):

A properly crafted test suite invites refactoring :)

class Anything:
'''wildcard: matches anything'''
def __eq__(self, other):
return True
Anything = Anything() # bad style, I know

def sliceIndex(seq, sub, start=0):
'''search starting at 'start' for sub in seq, return index of match
or -1'''
try:
i = seq.index(sub[0], start)
while i >= 0:
if seq[i:i+len(sub)] == sub:
return i
i = seq.index(sub[0], i+1)
except ValueError:
pass
return -1
def test():
case1 = ['Rita', 'Sue', 'Bob']
alist = 'Rita Mary Jane Bob Sue Carl Hans Rita Bob Sue'.split()
assert sliceIndex([], case1) == -1
assert sliceIndex(alist, case1) == -1

alist = 'Rita Mary Jane Bob Rita Carl Bob Hans Rita Sue Bob Sue
Rita Sue Bob'.split()
assert sliceIndex(alist, case1) == 8
assert sliceIndex(alist, case1, 9) == 12
assert sliceIndex(alist, case1, 13) == -1

case2 = ['Rita', Anything, 'Bob']
assert sliceIndex(alist, case2) == 4
assert sliceIndex(alist, case2, 5) == 8
assert sliceIndex(alist, case2, 9) == 12


if __name__ == '__main__':
test()
 
S

Shane Holloway (IEEE)

You can do it with list List Comprehensions:
BigList = ['Jean', 'Eric', 'Remy', 'Anne', 'Denis', 'Alain', 'Armel',
'Louis']
SmallList = ['Eric', 'Denis', 'Georges', 'Jean']

if ( [x for x in SmallList if x in BigList] == SmallList ):
print "They were found"
else:
print "They are not in list"


[x for x in SmallList if x in BigList] evaluates to a list with common
elements of SmallList and BigList

A little change:

Difference = [x for x in SmallList if x not in BigList]
if not Difference:
print "They were found"
else:
print Difference, "were not found in the list"
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,038
Latest member
OrderProperKetocapsules

Latest Threads

Top