如何在属性上找到具有相同函数返回值的列表的两项?

时间:2018-07-13 00:13:48

标签: python

给出基本类Item

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

此类的对象列表(项的数量可以大得多):

items = [ Item(0), Item(11), Item(25), Item(16), Item(31) ]

和函数compute处理并返回一个值。

在使用属性compute时,如何找到列表中两项,函数val返回相同的值?如果未找到任何内容,则应引发异常。如果有两个以上的项目相匹配,则简单地返回其中任何两个项目。

例如,让我们定义compute

def compute( x ):
    return x % 10

排除的配对为:(Item(11), Item(31))

3 个答案:

答案 0 :(得分:1)

您可以检查结果值集的长度:

class Item(object):
  def __init__(self, val):
    self.val = val
  def __repr__(self):
    return f'Item({self.val})'

def compute(x):
  return x%10

items = [ Item(0), Item(11), Item(25), Item(16), Item(31)]
c = list(map(lambda x:compute(x.val), items))
if len(set(c)) == len(c): #no two or more equal values exist in the list
  raise Exception("All elements have unique computational results")

要查找具有相似计算结果的值,可以使用字典:

from collections import Counter
new_d = {i:compute(i.val) for i in items}
d = Counter(new_d.values())
multiple = [a for a, b in new_d.items() if d[b] > 1]

输出:

[Item(11), Item(31)]

一种用于查找是否存在多个具有相同计算值的对象的更有效的方法是使用any,这需要对Counter对象进行一次传递,而将setlen需要多次迭代:

if all(b == 1 for b in d.values()):
   raise Exception("All elements have unique computational results")

答案 1 :(得分:0)

可以使用包含val_to_it由计算的Item键控的字典val

val_to_it = {}
for it in items:
    computed_val = compute(it.val)
    # Check if an Item in val_to_it has the same computed val
    dict_it = val_to_it.get(computed_val)
    if dict_it is None:
        # If not, add it to val_to_it so it can be referred to 
        val_to_it[computed_val] = it
    else:
        # We found the two elements!
        res = [dict_it, it]
        break
else:
    raise Exception( "Can't find two items" )

可以for块进行重写以处理n个元素:

for it in items:
    computed_val = compute(it.val)
    dict_lit = val_to_it.get(computed_val)
    if dict_lit is None:
        val_to_it[computed_val] = [it]
    else:
        dict_lit.append(it)
        # Check if we have the expected number of elements
        if len(dict_lit) == n:
            # Found n elements!
            res = dict_lit
            break

答案 2 :(得分:0)

假设compute返回的值是可散列的(例如float值),则可以使用字典来存储结果。

您不需要做任何花哨的事情,例如存储所有产生结果的项目的multidict。一旦看到重复,就完成了。除了更简单之外,这还意味着我们在找到匹配项后就将搜索短路,甚至无需在其余元素上调用compute

def find_pair(items, compute):
    results = {}
    for item in items:
        result = compute(item.val)
        if result in results:
            return results[result], item
        results[result] = item
    raise ValueError('No pair of items')