views:

140

answers:

6

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 up with, but it doesn't work!

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

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
matt b
Why iterate manually over `col`? `for i in col: if a==i` should do.
Tim Pietzcker
can't use 'in' operator
Gusto
@Gusto: In `for i in iterable`, the `in` is not an operator. Just a keyword required by the grammer.
delnan
+4  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
Tim Čas
second way is using 'in' operator, which is not allowed. The two others do nothing i.e is_member([1], [3,4,1]) return False in both cases
Gusto
I thought "in" was only unallowed in direct use. Anyways, you're mixing up the arguments, it's `is_member([3, 4, 1], 1)` (note that 2nd isn't an array).
Tim Čas
+2  A: 

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
tokland
@Tim: as a lazy generator expression, it will break on the first match.
tokland
Yes, sorry (and +1); I had timed a similar but subtly different solution.
Tim Pietzcker
+1  A: 

Recursive solution:

def is_member(value, array):
    if len(array) == 0:
        return False
    return value == array[0] or is_member(value, array[1:])
Magnus Hoff
This is exactly what I need! Thanks everyone for the efforts.
Gusto
I wouldn't accept this unless your trying to get a stack overflow...
mathepic
And now for the real question: What makes this acceptable that doesn't make the other answers acceptable? Stay tuned. Question should be tagged "quiz" ;)
Magnus Hoff
+1  A: 

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.

wheaties
A: 

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.

James Cunningham

related questions