有效计算真假的方法

时间:2013-10-07 15:41:45

标签: python algorithm python-2.7 counting

这可能是一个微不足道的问题,但我想更多地了解其他更聪明有效的解决方法。

我有一个项目列表,每个项目都有一个属性a,其值为二进制。

  • 如果列表中的每个项目都有a == 0,那么我会设置一个单独的变量b = 0
  • 如果列表中的每个项目都有a == 1,那么我设置b = 1
  • 如果列表中混合了a == 0a == 1,那么我就设置了 b = 2

我可以使用一个集来跟踪a值的类型,这样如果在遍历列表后集合中有两个项目,那么我可以设置b = 2,而如果集合中只有一个项目我只检索项目(0或1)并使用它来设置b

有更好的方法吗?

10 个答案:

答案 0 :(得分:26)

一次通过列表,没有构建额外的数据结构:

def zot(bs):
    n, s = len(bs), sum(bs)
    return 1 if n == s else 2 if s else 0

答案 1 :(得分:18)

我建议使用anyall。我想说这样做的好处是可读性而不是聪明或效率。例如:

>>> vals0 = [0, 0, 0, 0, 0]
>>> vals1 = [1, 1, 1, 1, 1]
>>> vals2 = [0, 1, 0, 1, 0]
>>> def category(vals):
...     if all(vals):
...         return 1
...     elif any(vals):
...         return 2
...     else:
...         return 0
... 
>>> category(vals0)
0
>>> category(vals1)
1
>>> category(vals2)
2

如果您愿意,可以缩短一点:

>>> def category(vals):
...     return 1 if all(vals) else 2 if any(vals) else 0
... 

这适用于__nonzero__(或Python 3中的__bool__)可以解释为具有true或false值的任何内容。

答案 2 :(得分:15)

有人提到代码高尔夫,所以无法抗拒@ senderle的变种:

[0,2,1][all(vals) + any(vals)]

简短说明:它使用布尔值作为整数等价物来索引所需响应的列表。如果all为真,那么any也必须为真,因此它们的总和为2any本身会1,而且匹配不会0。这些索引从列表中返回相应的值。

如果原始要求可以修改为1使用any2使用all,则返回{{1}的整数会更简单}

答案 3 :(得分:3)

使用字典:

zonk_values = {frozenset([0]): 0, frozenset([1]): 1, frozenset([0, 1]): 2}
def zonk(a):
    return zonk_values[frozenset(a)]

这也只需要一次通过列表。

答案 4 :(得分:2)

你也可以使用套装。

s = set([i.a for i in your_list])
if len(s) == 1:
    b = s.pop()
else:
    b = 2

答案 5 :(得分:2)

def zot(bs):
    return len(set(bs)) if sum(bs) else 0

答案 6 :(得分:1)

您可以定义两个布尔变量hasZerohasOne,如果在迭代列表时满足相应的值,则将它们设置为True。然后b = 2 hasZero and hasOneb = 1 hasOneb = 0 hasZero

另一种方式:您可以对列表中的所有a值求和。如果是sumA == len(list),那么b = 1,如果是sumA == 0,那么b = 0,如果是0 < sumA < len(list)b = 2

答案 7 :(得分:1)

短路解决方案。可能是你在Python中最有效的方式。

编辑:根据评论中的建议包括anyall

EDIT2:它现在是一个单行。

b = 1 if all(A) else 2 if any(A) else 0

答案 8 :(得分:0)

这类似于senderle的建议,但是为了访问对象的a属性而编写。

from random import randint

class Item(object):
    def __init__(self, a):
        self.a = a

all_zeros = [Item(0) for _ in xrange(10)]
all_ones = [Item(1) for _ in xrange(10)]
mixture = [Item(randint(0, 1)) for _ in xrange(10)]

def check(items):
    if all(item.a for item in items):
        return 1
    if any(item.a for item in items):
        return 2
    else:
        return 0

print 'check(all_zeros):', check(all_zeros)
print 'check(all_ones):', check(all_ones)
print 'check(mixture):', check(mixture)

答案 9 :(得分:0)

您可以使用列表iter ators:

>>> L = [0, 0, 0, 0, 0]
>>> L1 = [1, 1, 1, 1, 1]
>>> L2 = [0, 1, 0, 1, 0]
>>> def fn(i):
...     i = iter(i)
...     if all(i): return 1
...     return 2 if any(i) else 0
... 
>>> fn(L)
0
>>> fn(L1)
1
>>> fn(L2)
2