4

Say I have the following list:

L=[ [0,1,1,1],[1,0,1,1],[1,1,0,1],[1,1,1,0] ]

I want to write a code will take a list like this one and tell me if the number of '1s' in each individual list is equal to some number x. So if I typed in code(L,3) the return would be "True" because each list within L contains 3 '1s'. But if I entered code(L,2) the return would be "False". I'm new to all programming, so I'm sorry if my question is hard to understand. Any help would be appreciated.

0

4 Answers 4

7

To see if each sublist has 3 1's in it,

all( x.count(1) == 3 for x in L )

Or as a function:

def count_function(lst,number,value=1):
    return all( x.count(value) == number for x in lst )

L=[ [0,1,1,1],[1,0,1,1],[1,1,0,1],[1,1,1,0] ]
print(count_function(L,3)) #True
print(count_function(L,4)) #False
print(count_function(L,1,value=0)) #True
Sign up to request clarification or add additional context in comments.

2 Comments

+1 Upvote from me, but don't you think the better idea would be to have count_function(lst, number, value=1) function, as requested by OP?
@Tadeck -- Excellent suggestion (I didn't even think of using a default argument here). Thanks! Edited accordingly.
1

Assuming your lists contain only 1's and 0's, you can count the ones quite easily: sum(sl). You can get the set of unique counts for sub-lists and test that they all have three 1's as follows:

set( sum(sl) for sl in L ) == set([3])

While a little obscure compared to using the all() approach, this method also lets you test that all sub-lists have the same number of ones without having to specify the number:

len(set( sum(sl) for sl in L )) == 1

You can even "assert" that the sub-lists must all have the same number of 1's and discover that number in one operation:

[n] = set( sum(sl) for sl in L )

This assigns the number of 1's in each sub-list to n, but raises a ValueError if the sub-lists don't all have the same number.

4 Comments

This is clever, but it only works for binary sublists (correct me if I'm wrong) -- by that I mean lists with only two numbers in them, and one of the numbers has to be 0. But, +1 for a slightly more clever approach.
for example, L = [[1,2], [1,0,1,1]] (I think) will return True because the sum of each sublist is still 3. (but of course, this list violates the assumption you stated up front).
@mgilson: this is the strength of your solution. I believe Marcelo and I both based our answers on the assumption that lists can contain only zeros and ones. Seemingly we are correct, but your code is more flexible.
@Tadeck: Agreed, but that's just for simplicity's sake. If the assumption is wrong, simply change sum(sl) to sl.count(1), and everything else still works.
1

If L is your base list and n is the number of 1 you expect in each "sublist", then the check looks like this:

map(sum, l) == [n] * len(l)

The whole function, along with tests, looks like this:

>>> def check(l, n):
    return map(sum, l) == [n] * len(l)

>>> L=[ [0,1,1,1],[1,0,1,1],[1,1,0,1],[1,1,1,0] ]
>>> check(L, 3)
True
>>> check(L, 2)
False

EDIT: Alternative solutions include for example:

but I believe the cleanest approach is the one given by one of the other answerers:

all(i.count(1) == n for i in l)

It is even pretty self-explanatory.

7 Comments

@mgilson: Incorrect. For L = [[0,0,1,1],[1,1,1,1]] it returns False for both check(L, 2) and check(L, 4). Would you mind proving it?
@mgilson: Proof is here: ideone.com/QkO1j. I have tested all the Ls provided by you and others in this thread, with ns between 1 and 4. The results seem to be saying something other than you. Could you give an example?
You're right (sorry). I take back my former (incorrect) statement. I misunderstood what was happening in your solution.
One thing that is a little worrysome is the input list : L = [[1,2],[1,1,1]]. check(L,3) still returns True for this instance. It might be worth mentioning that you're assuming that the lists only hold 0's and 1's up front.
@mgilson: As I responded under some other answer, it was based on the actual question (lists containing only 0s and 1s). And indeed, your answer is more flexible (more than the actual question requires, but this is good). Do you want me to upvote your answer or what? ;)
|
0
def all_has(count, elem, lst)
    """ensure each iterable in lst has exactly `count` of `elem`"""
    return all(sub_list.count(elem) == count for sub_list in lst)

>>> L = [ [0,1,1,1],[1,0,1,1],[1,1,0,1],[1,1,1,0] ]
>>> all_has(3, 1, L)
True
>>> all_has(2, 0, L)
False

3 Comments

return all(sub_list.count(elem) == count for sub_list in lst) (list comprehension changed to generator expression) is cleaner and likely to perform faster since all will stop iterating on the first False where a list comprehension will evaluate every element. Of course, if you really want performance you still need to use benchmarks to determine which approach is faster.
I didn't know that. My first thought was it should be all( (x.count(e) == c for l in lst) ), but the parens aren't needed in all? Learn something new everyday.
The parens aren't needed in a function call where the generator is the only argument as a special case.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.