根据键的唯一性从列表中删除重复的字典

时间:2019-02-26 16:43:04

标签: python python-3.x

我的问题有点类似于这个问题:https://codereview.stackexchange.com/questions/175079/removing-key-value-pairs-in-list-of-dicts。本质上,我有一个字典列表,我想根据每个字典中两个(或多个)键的唯一组合从列表中删除重复项。

假设我有以下词典列表:

some_list_of_dicts = [
{'a': 1, 'b': 1, 'c': 1, 'd': 2, 'e': 4},
{'a': 1, 'b': 1, 'c': 1, 'd': 5, 'e': 1},
{'a': 1, 'b': 1, 'c': 1, 'd': 7, 'e': 8},
{'a': 1, 'b': 1, 'c': 1, 'd': 9, 'e': 6},
{'a': 1, 'b': 1, 'c': 2, 'd': 2, 'e': 3},
{'a': 1, 'b': 1, 'c': 3, 'd': 2, 'e': 3},
{'a': 1, 'b': 1, 'c': 4, 'd': 2, 'e': 3}
]

让我们假设abc的组合必须是唯一的;任何其他值都可以是它们想要的值,但是这三个值的组合对于此列表必须是唯一的。我想采用abc中唯一的组合,保留该组合,并丢弃组合相同的其他所有内容。

通过一些remove_duplicates函数运行新列表后,它看起来像这样:

new_list = [
{'a': 1, 'b': 1, 'c': 1, 'd': 2, 'e': 4},
{'a': 1, 'b': 1, 'c': 2, 'd': 2, 'e': 3},
{'a': 1, 'b': 1, 'c': 3, 'd': 2, 'e': 3},
{'a': 1, 'b': 1, 'c': 4, 'd': 2, 'e': 3}
]

我只能设法解决这个问题:

def remove_duplicates(old_list):

    uniqueness_check_list = []
    new_list = []

    for item in old_list:
        # The unique combination is 'a', 'b', and 'c'
        uniqueness_check = "{}{}{}".format(
            item["a"], item["b"], item["c"]
        )

        if uniqueness_check not in uniqueness_check_list:
            new_list.append(item)

        uniqueness_check_list.append(uniqueness_check)

    return new_list

但是,这感觉不太像Python。还有一个问题,就是我已经在函数中硬编码了哪些键必须是唯一的。如果我可以将其指定为函数本身的参数会更好,但同样,不确定执行此操作的最佳方式是什么。

2 个答案:

答案 0 :(得分:3)

您可以使用dict理解以相反的顺序从字典列表中构建一个dict,以便任何唯一组合中的第一个组合的值都优先。使用operator.itemgetter获取唯一键作为元组。最后按原始顺序再次颠倒:

from operator import itemgetter
list({itemgetter('a', 'b', 'c')(d): d for d in reversed(some_list_of_dicts)}.values())[::-1]

这将返回:

[{'a': 1, 'b': 1, 'c': 1, 'd': 2, 'e': 4},
 {'a': 1, 'b': 1, 'c': 2, 'd': 2, 'e': 3},
 {'a': 1, 'b': 1, 'c': 3, 'd': 2, 'e': 3},
 {'a': 1, 'b': 1, 'c': 4, 'd': 2, 'e': 3}]

答案 1 :(得分:1)

借助跟踪重复项的功能,您可以使用一些列表理解:

  Rectangle[] zombies = new Rectangle[60];

        Timer timer = new Timer();

        int spawnedZombies = 0;

        public Zombie(float x, float y, ID id, SpriteSheet ss) {
            super(x, y, id, ss);

            Delay();
        }

        public void Delay(){
            timer.schedule(task, 0, 1000);

        }

        TimerTask task = new TimerTask()
        {
            public void run()
            {
                Random rand = new Random();
                int result = rand.nextInt(6);

                if(result == 0){
                    x = 1000;
                    y = 200;
                }

                if(result == 1){
                    x = 100;
                    y = 200;
                }

                if(result == 2){
                    x = 100;
                    y = 600;
                }

                if(result == 3){
                    x = 1000;
                    y = 600;
                }

                if(result == 4){
                    x = 100;
                    y = 900;
                }

                if(result == 5){
                    x = 1000;
                    y = 900;
                }
        spawnedZombies++;
        zombies[spawnedZombies - 1] = new Rectangle((int)x, (int)y, 32, 48);


                if(spawnedZombies == zombies.length){
                    task.cancel();
                }

            }
        };

要使用:

def remove_duplicates(old_list, cols=('a', 'b', 'c')):
    duplicates = set()

    def is_duplicate(item):
        duplicate = item in duplicates
        duplicates.add(item)
        return duplicate

    return [x for x in old_list if not is_duplicate(tuple([x[col] for col in cols]))]

您还可以提供不同的列来输入:

>>> remove_duplicates(some_list_of_dicts)
[
    {'a': 1, 'c': 1, 'b': 1, 'e': 4, 'd': 2}, 
    {'a': 1, 'c': 2, 'b': 1, 'e': 3, 'd': 2}, 
    {'a': 1, 'c': 3, 'b': 1, 'e': 3, 'd': 2}, 
    {'a': 1, 'c': 4, 'b': 1, 'e': 3, 'd': 2}
]