Python仅使用列表推导即可动态计算没有重复的列表

时间:2018-12-18 18:57:39

标签: python list-comprehension

这是一个荒谬而又怪异的用例,但请耐心接受,我对清单的理解是这样的:

"reading_types": [
    {
        "name": rt.reading_type,
        "value": rt.reading_type_id,
    }
    for unit in item.units
    for rt in unit.reading_types
],

在后端api调用中。 效果很好,因为最终结果几乎总是重复。如何确保不返回任何重复项?

这实际上是在另一个列表推导内部发生的,我无法在任何时候引用列表来删除重复项,因此我必须在列表推导本身内这样做。

我尝试使用set

set([
    {
        "name": rt.reading_type,
        "value": rt.reading_type_id,
    }
    for unit in item.units
    for rt in unit.reading_types
])

但这会导致错误:unhashable type: dict

4 个答案:

答案 0 :(得分:6)

这个想法是使您的结构可哈希而不破坏得太多,因此您可以将它们恢复到原来的状态。

您可以将字典转换为dict_items,然后转换为tuples(现在我们可以将其放入set,因为数据是可哈希的),在其上应用set,并转换回字典:

input_list = [{"name":"name1","id":"id1"},{"name":"name2","id":"id2"},
{"name":"name1","id":"id1"}]

output_list = [dict(items) for items in {tuple(a.items()) for a in input_list}]

之所以可行,是因为子字典的值是可哈希的(字符串)。如果它们是字典,我们也必须将其转换。

结果:

[{'id': 'id1', 'name': 'name1'}, {'id': 'id2', 'name': 'name2'}]

Jon Clements的另一种解决方案,不使用set,而是构建字典(使用字典理解),并使用键唯一性来破坏重复项,然后仅提取值:

list({tuple(d.items()):d for d in input_list}.values())

答案 1 :(得分:2)

您可以在set中使用namedtuple代替字典。作为namedtuple的不可变对象,它们是可哈希的,而字典则不是。您还可以直接使用集合理解:

from collections import namedtuple

reading_type = namedtuple("reading_type", ["name", "value"])

{reading_type(rt.reading_type, rt.reading_type_id) 
    for unit in item.units
    for rt in unit.reading_types}

答案 2 :(得分:0)

这不是列表理解,但是您可以使用<?php header('Content-type: application/json'); include('connect.php'); $obj = json_decode(file_get_contents('php://input'), TRUE); $gymId = $obj['gym_id']; $query = "select * from tbl_fees where gym_id = $gymId"; $result = mysqli_query($sql, $query); $row = $result->fetch_assoc(); $amount = $row['month'.$months]; echo json_encode($row); ?> unique_everseen recipe,也可以在第三方库中使用,例如more_itertools.unique_everseen

itertools

诀窍是确保您可以对字典进行哈希处理,这是通过将每个字典转换为已排序的元组的元组来执行的。在内部,该算法通过维持“可见的” from more_itertools import unique_everseen input_list = [{"name":"name1","id":"id1"},{"name":"name2","id":"id2"}, {"name":"name1","id":"id1"}] res = list(unique_everseen(input_list, key=lambda d: tuple(sorted(d.items())))) print(res) [{'name': 'name1', 'id': 'id1'}, {'name': 'name2', 'id': 'id2'}] 值并仅产生未出现在set中的值来进行工作,否则将其添加。

答案 3 :(得分:-1)

您可以将整个列表包装在另一个理解中,以repr的每个条目使用,并在其上使用set

set([repr(val) for val in [...]])