开发者

List membership in Python without "in"

How to define a function is_member() that takes a value (i.e. a number, string, etc) x and a list of values a, and returns True if x is a member of a, False otherwise. (Note that this is exactly what the in operator does, but for the sake of the exercise I should pretend Python did not have this operator.

This is what I've come 开发者_C百科up with, but it doesn't work!

def is_member(x, a):
   return x == a[::]


I can think of two (edit: three) ways to do this:

First:

def is_member(array, value):
    try:
        array.index(value)
    except ValueError:
        return False
    else:
        return True

Second:

def is_member(array, value):
    for item in array:
        if item == value:
            return True
    return False

EDIT: Also, third:

def is_member(array, value):
    return array.count(value) > 0


Recursive solution:

def is_member(value, array):
    if len(array) == 0:
        return False
    return value == array[0] or is_member(value, array[1:])


Using a generator expression (note that this in operator has nothing to do with the another one)

def is_member(x, a):
   return any(x == y for y in a)

>>> is_member(10, xrange(1000000000000000))
True


You could simply just iterate over every element in the list then:

def is_member(col, a):
    for i in xrange(len(col)):
        if a == col[i]: return True
    return False


>> a = [1,2,3,4]
>> is_member(a, 2)
True
>> is_member(a, 5)
False


Without using the "in" operator:

from itertools import imap
def is_member( item, array ):
    return any( imap(lambda x: x == item, array ) )

which will cycle through the items of the list, one at a time, and short circuit when it hits a value that is True.


Well, there are a lot of ways to do this, of course -- but you're a little hamstrung by the prohibition of "in" anywhere in the code. Here are a few things to try.

Variations on a theme ...

def is_member(item, seq):
    return sum(map(lambda x: x == item, seq)) > 0

def is_member(item, seq):
    return len(filter(lambda x: x != item, seq)) != len(seq)

You may have heard that asking for forgiveness is better than asking for permission ...

def is_member(item, seq):
    try:
        seq.index(item)
        return True
    except:
        return False

Or something a little more functional-flavored ...

import itertools, operator, functools
def is_member(item, seq):
    not_eq = functools.partial(operator.ne, item)
    return bool(list(itertools.dropwhile(not_eq, seq)))

But, since your requirements preclude the use of the looping construct which would be most reasonable, I think the experts would recommend writing your own looping framework. Something like ...

def loop(action, until):
    while True:
        action()
        if until():
            break

def is_member(item, seq):
    seq   = seq
    sigil = [False]

    def check():
        if seq[0] == item:
            sigil[0] = True
    def til():
        seq.remove(seq[0])
        return not len(seq)

    loop(check, til)

    return sigil[0]

Let us know how it goes.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜