Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > A and B but not C in list

Reply
Thread Tools

A and B but not C in list

 
 
CM
Guest
Posts: n/a
 
      01-23-2011
In Python, is there a recommended way to write conditionals of the
form:

"if A and B but not C or D in my list, do something." ?

I may also have variations on this, like "if A but not B, C, or D".

Do I have to just write out all the if and elifs with all possible
conditions, or is there a handier and more code-maintainable way to
deal with this?

Thanks.




 
Reply With Quote
 
 
 
 
Corey Richardson
Guest
Posts: n/a
 
      01-23-2011
On 01/23/2011 04:05 PM, CM wrote:
> In Python, is there a recommended way to write conditionals of the
> form:
>
> "if A and B but not C or D in my list, do something." ?
>
> I may also have variations on this, like "if A but not B, C, or D".
>
> Do I have to just write out all the if and elifs with all possible
> conditions, or is there a handier and more code-maintainable way to
> deal with this?
>
> Thanks.
>
>
>
>


if (A in list and B in list) and (C not in list or D not in list):
pass

I'm sure the gurus on this list can come up with something better.
 
Reply With Quote
 
 
 
 
Chris Rebert
Guest
Posts: n/a
 
      01-23-2011
On Sun, Jan 23, 2011 at 1:05 PM, CM <(E-Mail Removed)> wrote:
> In Python, is there a recommended way to write conditionals of the
> form:
>
> "if A and B but not C or D in my list, do something." *?
>
> I may also have variations on this, like "if A but not B, C, or D".
>
> Do I have to just write out all the if and elifs with all possible
> conditions, or is there a handier and more code-maintainable way to
> deal with this?


Assuming your conditions all involve membership testing...
Use the built-in any() and all() functions. For your first example:

wanteds = [A, B]
unwanteds = [C, D]
if all(wanted in your_list for wanted in wanteds) and \
not any(unwanted in your_list for unwanted in unwanteds):
do_whatever()

You could pull this out into a separate function if you wish.

Cheers,
Chris
--
http://blog.rebertia.com
 
Reply With Quote
 
Steven D'Aprano
Guest
Posts: n/a
 
      01-23-2011
On Sun, 23 Jan 2011 22:34:33 +0100, Christian Heimes wrote:

> It's easier and faster if you convert the lists to sets first:
>
> your_set = set(your_list)
>
> if your_set.issuperset(set([A, B])) and your_set.isdisjoint(set([C,
> D])):
> ...


"Easier" is a close thing. I find this easier to remember and write than
set processing, even if it is a couple of characters longer:

if all(x in your_list for x in (A, B)) and not any(x in your_list for x
in (C, D)):
...

And as for "faster", surely that will depend on the number of elements in
your_list? The conversion from list to set doesn't happen for free, and
it's likely that for small enough lists, that time may exceed any time
savings you would otherwise gain.


--
Steven
 
Reply With Quote
 
Terry Reedy
Guest
Posts: n/a
 
      01-24-2011
On 1/23/2011 4:05 PM, CM wrote:
> In Python, is there a recommended way to write conditionals of the
> form:
>
> "if A and B but not C or D in my list, do something." ?
>
> I may also have variations on this, like "if A but not B, C, or D".
>
> Do I have to just write out all the if and elifs with all possible
> conditions, or is there a handier and more code-maintainable way to
> deal with this?


The straightforward code

if a in L and b in L and c not in L and d not in L

scans the list 4 times. One scan be be done generically as follows:

def req_pro(iterable, required = set(), prohibited = set()):
for item in iterable:
if item in prohibited:
return False
elif item in required:
required.remove(item)
else:
return not required # should now be empty

if req_pro(my_list, {A,B}, {C,D}): ...
# untested, of course..

--
Terry Jan Reedy

 
Reply With Quote
 
Ian Kelly
Guest
Posts: n/a
 
      01-24-2011
On Sun, Jan 23, 2011 at 2:34 PM, Christian Heimes <(E-Mail Removed)> wrote:
> your_set = set(your_list)
>
> if your_set.issuperset(set([A, B])) and your_set.isdisjoint(set([C, D])):


if your_set.intersection([A, B, C, D]) == set([A, B]):
...

Cheers,
Ian
 
Reply With Quote
 
Peter Otten
Guest
Posts: n/a
 
      01-24-2011
Ian Kelly wrote:

> On Sun, Jan 23, 2011 at 2:34 PM, Christian Heimes <(E-Mail Removed)>
> wrote:
>> your_set = set(your_list)
>>
>> if your_set.issuperset(set([A, B])) and your_set.isdisjoint(set([C, D])):

>
> if your_set.intersection([A, B, C, D]) == set([A, B]):
> ...


You can avoid converting your_list to a set with (using 2.7/3.x notation)

if {A, B, C, D}.intersection(your_list) == {A, B}:
...

The items in your_list still have to be hashable, so the approach is not as
general as

if (all(required in your_list for required in (A, B)) and
not any(forbidden in your_list for forbidden in (C, D))):
...

or similar.

Also, it's not as easy to understand, so don't forget the explaining comment
if you use the set-based approach.

Peter
 
Reply With Quote
 
Boris Borcic
Guest
Posts: n/a
 
      01-24-2011
Terry Reedy wrote:
>
> The straightforward code
>
> if a in L and b in L and c not in L and d not in L
>
> scans the list 4 times.


of course for a single scan one can setify the list and write

S=set(L)
if a in S and b in S and c not in S and d not in S

or even, I guess, something like

{a,b} <= S and not S & {c,d}

also, I suppose that in some settings a,b,c,d could be made to belong to a class
that has defined eg

__nonzero__ = __bool__ = S.__contains__

so that the if statement would become

if a and b and not c and not d

btw, did anybody ask the OP which if any of A,B,C,D otoh and L otoh would vary
fastest ?

Whatever, BB


 
Reply With Quote
 
Arnaud Delobelle
Guest
Posts: n/a
 
      01-26-2011
Terry Reedy <(E-Mail Removed)> writes:

> On 1/23/2011 4:05 PM, CM wrote:
>> In Python, is there a recommended way to write conditionals of the
>> form:
>>
>> "if A and B but not C or D in my list, do something." ?
>>
>> I may also have variations on this, like "if A but not B, C, or D".
>>
>> Do I have to just write out all the if and elifs with all possible
>> conditions, or is there a handier and more code-maintainable way to
>> deal with this?

>
> The straightforward code
>
> if a in L and b in L and c not in L and d not in L
>
> scans the list 4 times. One scan be be done generically as follows:
>
> def req_pro(iterable, required = set(), prohibited = set()):
> for item in iterable:
> if item in prohibited:
> return False
> elif item in required:
> required.remove(item)
> else:
> return not required # should now be empty
>
> if req_pro(my_list, {A,B}, {C,D}): ...
> # untested, of course..


But what's better? Four fast list scans or one slow one?

--
Arnaud
 
Reply With Quote
 
CM
Guest
Posts: n/a
 
      01-28-2011
Thanks, everyone, for your suggestions.

-Che
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
List index out of range, but list has enough elements Costin Gamenț Python 1 11-09-2010 09:37 AM
after del list , when I use it again, prompt 'not defined'.how could i delete its element,but not itself? python Python 7 06-03-2006 05:08 PM
Connect to 802.11b but not 802.11g... but used to be able to...? jbraly@gmail.com Wireless Networking 1 03-13-2006 11:05 PM
Difference Between List x; and List x(); , if 'List' is a Class? roopa C++ 6 08-27-2004 06:18 PM



Advertisments