寻找更pythonic的逻辑解决方案

Posted

技术标签:

【中文标题】寻找更pythonic的逻辑解决方案【英文标题】:Looking for a more pythonic logical solution 【发布时间】:2012-06-04 17:16:09 【问题描述】:

我在Coding Bat做一些练习题,遇到了这个..

Given 3 int values, a b c, return their sum. However, if one of the values is the same as another of the values, it does not count towards the sum. 

lone_sum(1, 2, 3) → 6
lone_sum(3, 2, 3) → 2
lone_sum(3, 3, 3) → 0 

我的解决方案如下。

def lone_sum(a, b, c):
   sum = a+b+c
   if a == b:
     if a == c:
         sum -= 3 * a
     else:
         sum -= 2 * a
   elif b == c:
     sum -= 2 * b
   elif a == c:
     sum -= 2 * a
   return sum

有没有更 Pythonic 的方式来做到这一点?

【问题讨论】:

关于代码缩进,看这个***.com/editing-help。或者,单击 ?编辑框顶部的图标。 @mhawke:我遵循了 4 个空格缩进,但在预览中没有显示额外的缩进,所以有点困惑。感谢您编辑代码! 请感谢 Martin 的清理工作! 【参考方案1】:

另一种适用于任意数量参数的可能性:

from collections import Counter

def lone_sum(*args):
    return sum(x for x, c in Counter(args).items() if c == 1)

请注意,在 Python 2 中,您应该使用 iteritems 来避免构建临时列表。

【讨论】:

值得注意的是 Counter 仅适用于 Python >= 2.7 @Daniel:Python 2.7 现在应该是标准,我通常认为它是可用的。如果Counter 不可用,您可以使用defaultdict(int) 轻松构建等效版本 @NiklasB.,我敢猜测很多 Apple 用户仍在运行 2.6 或更低版本。 Apple 刚刚使用 OSX 10.7 升级到 2.7。 当前的 Debian 稳定版不包括 2.7,并且有许多环境使用更旧版本的 Python。大多数 GAE 应用程序仍然在 2.5 上运行。我遇到的很多 HPC 集群只支持 2.5。简单地声称“Python 2.7 现在应该是标准”并不符合现实。 @Sven:是的,也许不是这样。尽管如此,仍然存在几个纯 Python 实现 collections.Counter,如果它本身不可用,则可以使用它们。【参考方案2】:

怎么样:

def lone_sum(*args):
      return sum(v for v in args if args.count(v) == 1)

【讨论】:

对于只有三个参数,这个实现可能没问题,但它不应该用于大量参数,因为它是 O(n²)。它完全让我无法理解为什么“没有任何进口”本身应该被视为一种优势。 @SvenMarnach:你可能是对的,但这是对 OP 问题的完美回答。 @BandGap:我最喜欢 Niklas 的回答。它同样简短、易读且 O(n)。【参考方案3】:

对于任意数量的参数,更通用的解决方案是

def lone_sum(*args):
    seen = set()
    summands = set()
    for x in args:
        if x not in seen:
            summands.add(x)
            seen.add(x)
        else:
            summands.discard(x)
    return sum(summands)

【讨论】:

不适用于lone_sum(3, 3, 3);您需要在从 summands 中删除之前添加一个检查。 @SanjayT.Sharma:有一个版本存在这个问题大约一分钟,但当前版本很好。【参考方案4】:

可以使用 defaultdict 筛选出任何多次出现的元素。

from collections import defaultdict

def lone_sum(*args):
  d = defaultdict(int)
  for x in args:
    d[x] += 1

  return sum( val for val, apps in d.iteritems() if apps == 1 )

【讨论】:

这在精神上与 Niklas B 采用的方法相似——他也更简洁。 也开始在 Python 中使用 4 个空格缩进!请参阅 PEP-8 了解原因。【参考方案5】:
def lone_sum(a, b, c):
    z = (a,b,c)
    x = []
    for item in z:
        if z.count(item)==1:
            x.append(item)
    return sum(x)

【讨论】:

【参考方案6】:

我在 Codingbat 上尝试过,但它不起作用,虽然它在代码编辑器上可以。

def lone_sum(a, b, c): s = set([a,b,c]) 返回总和

【讨论】:

【参考方案7】:

与您的方法非常相似:

def lone_sum(a, b, c):

  if a != b and b != c and c != a:
    return a + b + c

  elif a == b == c:
    return 0 

  elif a == b:
    return c
  elif b == c:
    return a
  elif c == a:
    return b

由于如果 2 个值相同,代码将自动返回 剩余价值。

【讨论】:

以上是关于寻找更pythonic的逻辑解决方案的主要内容,如果未能解决你的问题,请参考以下文章

让 Grails 控制器更干燥?

熊猫中的元素异或

当逻辑语句的结果发生变化时如何执行回调?

架构设计模式

逻辑回归理解及代码实现

我正在使用 excel 构建网站 - 寻找替代方案