代码之家  ›  专栏  ›  技术社区  ›  Seth Killian

python对象的自定义过滤函数

  •  0
  • Seth Killian  · 技术社区  · 6 年前

    
    # For the sake of example - assume that a hashing function is implemented based on the score
    
    class Object
       def __init__(self):
           score = 0
       def __repr__(self):
           return f'<Object {self.score}>'
    
    pairs = [(1, <Object 1>), (1, <Object 1>), (3, <Object 7>), (9, <Object 3>), (9, <Object 4>)]
    
    filtered_pairs = [(1, <Object 1>), (3, <Object 7>), (9, <Object 4>)]
    
    

    我知道我可以打电话 set

    我知道我可以从itertools中进行groupby,并使用分数作为键实现排序,然后从每个组中获取最后一项,但我想知道是否有更有效的方法。

    0 回复  |  直到 6 年前
        1
  •  1
  •   Mark    6 年前

    既然你在考虑一套,我想原来的顺序并不重要。如果是这样,一个选项是添加 __lt__ 方法,以便可以按分数比较对象。然后按相反的顺序对元组进行排序,按整数分组,并从每个组中获取第一个项。在代码中比解释更容易看到:

    from itertools import groupby
    
    class myObject:
        def __init__(self, score):
            self.score = score
        def __repr__(self):
            return f'<Object {self.score}>'
        def __lt__(self, other):
            return self.score < other.score
    
    pairs = [(1, myObject(1)), (1, myObject(1)), (3, myObject(7)), (9, myObject(3)), (9, myObject(4))]
    
    [next(v) for k, v in groupby(sorted(pairs, reverse=True), key=lambda x: x[0])]
    

    结果

    [(9, <Object 4>), (3, <Object 7>), (1, <Object 1>)]
    
        2
  •  2
  •   Guy    6 年前

    你可以用 itertools.groupby 按第一个值分组并对结果使用max

    from itertools import groupby
    
    
    class Object:
    
        def __init__(self, score):
            self.score = score
    
        def __repr__(self):
            return f'<Object {self.score}>'
    
    
    pairs = [(1, Object(1)), (1, Object(1)), (3, Object(7)), (9, Object(3)), (9, Object(4))]
    
    filtered_pairs = [max(list(elem), key=lambda x: x[1].score) for grp, elem in groupby(pairs, lambda x: (x[0]))]
    print(filtered_pairs)
    

    [(1, <Object 1>), (3, <Object 7>), (9, <Object 4>)]
    
        3
  •  0
  •   Grismar    6 年前

    像这样的:

    from collections import namedtuple
    
    Pair = namedtuple('Pair', ['id', 'score'])
    
    pairs = [Pair(*t) for t in [(1, 1), (1, 1), (3, 7), (9, 3), (9, 4)]]
    
    best_pairs = {}
    for p in pairs:
        if p.id not in best_pairs or p.score > best_pairs[p.id]:
            best_pairs[p.id] = p.score
    
    pairs = [Pair(*t) for t in best_pairs.items()]
    
    print(pairs)
    

    namedtuple 只是作为你的 Object 以及转换回 pairs 因为只有在你不喜欢字典的情况下,才有一个成对的列表 best_pairs .

    [Pair(id=1, score=1), Pair(id=3, score=7), Pair(id=9, score=4)]
    
        4
  •  0
  •   kaya3 Amit Bera    6 年前

    可以按分数排序、转换为dict(以便最大分数为dict值)和转换回元组列表:

    class Object:
        def __init__(self, score):
            self.score = score
        def __repr__(self):
            return f'<Object {self.score}>'
        def __gt__(self, other):
            return self.score > other.score
    
    
    pairs = [(1, Object(1)), (1, Object(1)), (3, Object(7)), (9, Object(4)), (9, Object(3))]
    filtered_pairs = list(dict(sorted(pairs)).items())