10

友達、私は辞書のリストを持っています:

my_list = 
[
{'oranges':'big','apples':'green'},
{'oranges':'big','apples':'green','bananas':'fresh'},
{'oranges':'big','apples':'red'},
{'oranges':'big','apples':'green','bananas':'rotten'}
]

部分的な重複を排除した新しいリストを作成したい。

私の場合、この辞書は削除する必要があります。

{'oranges':'big','apples':'green'}

、それはより長い辞書を複製するためです:

{'oranges':'big','apples':'green','bananas':'fresh'}
{'oranges':'big','apples':'green','bananas':'rotten'}

したがって、望ましい結果は次のとおりです。

[
{'oranges':'big','apples':'green','bananas':'fresh'},
{'oranges':'big','apples':'red'},
{'oranges':'big','apples':'green','bananas':'rotten'}
]

どうやってするの?どうもありがとう!

4

5 に答える 5

5

最初の[まあ、2番目に、いくつかの編集を加えて..]頭に浮かぶのはこれです:

def get_superdicts(dictlist):
    superdicts = []
    for d in sorted(dictlist, key=len, reverse=True):
        fd = set(d.items())
        if not any(fd <= k for k in superdicts):
            superdicts.append(fd)
    new_dlist = map(dict, superdicts)
    return new_dlist

与える:

>>> a = [{'apples': 'green', 'oranges': 'big'}, {'apples': 'green', 'oranges': 'big', 'bananas': 'fresh'}, {'apples': 'red', 'oranges': 'big'}, {'apples': 'green', 'oranges': 'big', 'bananas': 'rotten'}]
>>> 
>>> get_superdicts(a)
[{'apples': 'red', 'oranges': 'big'}, 
 {'apples': 'green', 'oranges': 'big', 'bananas': 'rotten'}, 
 {'bananas': 'fresh', 'oranges': 'big', 'apples': 'green'}]

[もともとfrozenset、ある種の巧妙な集合操作ができると考えて、here を使用していましたが、明らかに何も思いつきませんでした。]

于 2012-12-28T07:26:36.510 に答える
3

次の実装を試してください

私の実装では、反復回数を減らすために2つのペアの組み合わせのみを事前に並べ替えて選択していることに注意してください。これにより、キーのサイズが常に干し草と同じかそれ以下になります。

>>> my_list =[
{'oranges':'big','apples':'green'},
{'oranges':'big','apples':'green','bananas':'fresh'},
{'oranges':'big','apples':'red'},
{'oranges':'big','apples':'green','bananas':'rotten'}
]

#Create a function remove_dup, name it anything you want
def remove_dup(lst):
    #import combinations for itertools, mainly to avoid multiple nested loops
    from itertools import combinations
    #Create a generator function dup_gen, name it anything you want
    def dup_gen(lst):
        #Now read the dict pairs, remember key is always shorter than hay in length
        for key, hay in combinations(lst, 2):
            #if key is in hay then set(key) - set(hay) = empty set
            if not set(key) - set(hay):
                #and if key is in hay, yield it
                yield key
    #sort the list of dict based on lengths after converting to a item tuple pairs
    #Handle duplicate elements, thanks to DSM for pointing out this boundary case
    #remove_dup([{1:2}, {1:2}]) == []
    lst = sorted(set(tuple(e.items()) for e in lst), key = len)
    #Now recreate the dictionary from the set difference of
    #the original list and the elements generated by dup_gen
    #Elements generated by dup_gen are the duplicates that needs to be removed
    return [dict(e) for e in set(lst) - set(dup_gen(lst))]

remove_dup(my_list)
[{'apples': 'green', 'oranges': 'big', 'bananas': 'fresh'}, {'apples': 'green', 'oranges': 'big', 'bananas': 'rotten'}, {'apples': 'red', 'oranges': 'big'}]

remove_dup([{1:2}, {1:2}])
[{1: 2}]

remove_dup([{1:2}])
[{1: 2}]

remove_dup([])
[]

remove_dup([{1:2}, {1:3}])
[{1: 2}, {1: 3}]

より高速な実装

def remove_dup(lst):
    #sort the list of dict based on lengths after converting to a item tuple pairs
    #Handle duplicate elements, thanks to DSM for pointing out this boundary case
    #remove_dup([{1:2}, {1:2}]) == []
    lst = sorted(set(tuple(e.items()) for e in lst), key = len)
        #Generate all the duplicates
    dups = (key for key, hay in combinations(lst, 2) if not set(key).difference(hay))
    #Now recreate the dictionary from the set difference of
    #the original list and the duplicate elements
    return [dict(e) for e in set(lst).difference(dups)]
于 2012-12-28T07:11:10.200 に答える
2

使用できる実装の1つは次のとおりです。-

>>> my_list = [
{'oranges':'big','apples':'green'},
{'oranges':'big','apples':'green','bananas':'fresh'},
{'oranges':'big','apples':'red'},
{'oranges':'big','apples':'green','bananas':'rotten'}
]

>>> def is_subset(d1, d2):
        return all(item in d2.items() for item in d1.items())
        # or
        # return set(d1.items()).issubset(set(d2.items()))

>>> [d for d in my_list if not any(is_subset(d, d1) for d1 in my_list if d1 != d)]
[{'apples': 'green', 'oranges': 'big', 'bananas': 'fresh'}, 
 {'apples': 'red', 'oranges': 'big'}, 
 {'apples': 'green', 'oranges': 'big', 'bananas': 'rotten'}]

の各dictについてdmy_list-

any(is_subset(d, d1) for d1 in my_list if d1 != d)

dict内の他のサブセットであるかどうかをチェックしmy_listます。を返す場合True、サブセットがである少なくとも1つのdictがありdます。それで、リストnotから除外するためにそれを取りdます。

于 2012-12-28T07:16:11.130 に答える
1

短い答え

def is_subset(d1, d2):
    # Check if d1 is subset of d2
    return all(item in d2.items() for item in d1.items())

filter(lambda x: len(filter(lambda y: is_subset(x, y), my_list)) == 1, my_list)
于 2012-12-28T07:22:33.600 に答える
1

私はそれがより良い時間順序を持っていると思います:

def is_subset(a, b):
    return not set(a) - set(b)

def remove_extra(my_list):
    my_list = [d.items() for d in my_list]
    my_list.sort()

    result = []
    for i in range(len(my_list) - 1):
        if not is_subset(my_list[i], my_list[i + 1]):
            result.append(dict(my_list[i]))
    result.append(dict(my_list[-1]))

    return result

print remove_extra([
        {'oranges':'big','apples':'green'},
        {'oranges':'big','apples':'green','bananas':'fresh'},
        {'oranges':'big','apples':'red'},
        {'oranges':'big','apples':'green','bananas':'rotten'}
    ])
于 2012-12-28T07:27:44.543 に答える