Movatterモバイル変換


[0]ホーム

URL:


Welcome, guest|Sign In|My Account|Store|Cart
ActiveState Code »Recipes
LanguagesTagsAuthorsSets

OrderedSet(Python recipe)by Raymond Hettinger
ActiveState Code (http://code.activestate.com/recipes/576694/)

Set that remembers original insertion order.

Python, 67 lines
Copy to clipboard
 1 2 3 4 5 6 7 8 910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
importcollectionsclassOrderedSet(collections.MutableSet):def__init__(self,iterable=None):self.end=end=[]end+=[None,end,end]# sentinel node for doubly linked listself.map={}# key --> [key, prev, next]ifiterableisnotNone:self|=iterabledef__len__(self):returnlen(self.map)def__contains__(self,key):returnkeyinself.mapdefadd(self,key):ifkeynotinself.map:end=self.endcurr=end[1]curr[2]=end[1]=self.map[key]=[key,curr,end]defdiscard(self,key):ifkeyinself.map:key,prev,next=self.map.pop(key)prev[2]=nextnext[1]=prevdef__iter__(self):end=self.endcurr=end[2]whilecurrisnotend:yieldcurr[0]curr=curr[2]def__reversed__(self):end=self.endcurr=end[1]whilecurrisnotend:yieldcurr[0]curr=curr[1]defpop(self,last=True):ifnotself:raiseKeyError('set is empty')key=self.end[1][0]iflastelseself.end[2][0]self.discard(key)returnkeydef__repr__(self):ifnotself:return'%s()'%(self.__class__.__name__,)return'%s(%r)'%(self.__class__.__name__,list(self))def__eq__(self,other):ifisinstance(other,OrderedSet):returnlen(self)==len(other)andlist(self)==list(other)returnset(self)==set(other)if__name__=='__main__':s=OrderedSet('abracadaba')t=OrderedSet('simsalabim')print(s|t)print(s&t)print(s-t)

Runs on Py2.6 or later (and runs on 3.0 or later without any modifications).

Implementation based on a doubly linked link and an internal dictionary. This design gives OrderedSet the same big-Oh running times as regular sets including O(1) adds, removes, and lookups as well as O(n) iteration.

Tags:ordered,set

11 comments

Andrew Henshaw15 years, 1 month ago # |flag

In "__init__", iterable is checked to be "not None" before calling "update", which seems redundant because "update" does the same check before doing anything.

Adam Olsen15 years ago # |flag

Although this recipe is far superior in that it actually is a set, my older recipe doesn't require the cyclic GC to be collected.http://code.activestate.com/recipes/528878/ It'd be fairly easy to combine the two.

Adam, this recipe doesn't use or rely on GC. Individual links get deleted immediately whendiscard() is called. Likewise, when the whole set is no longer needed, the__del__ method neatly deletes clears all of the links without waiting for GC.

Also, FWIW, there is an alternate version of this recipe using weakrefs. Seerecipe 576696. Neither version needs GC.

Nagappan Alagappan14 years, 7 months ago # |flag

Hello Raymond,

I'm planing to use this module in LDTPv2 -http://ldtp.freedesktop.org under LGPLv2 license. If you have any objections, please write me to nagappan (at) gmail (dot) com. I have just mentioned your name in the file. I could not find your email id to specify in orderedset.py (http://cgit.freedesktop.org/ldtp/ldtp2/tree/ldtpd/orderedset.py). You can email me that as well, if you are interested with my proposal :)

You have done a wonderful job.

ThanksNagappan

Greg13 years, 8 months ago # |flag

The __eq__ operator for comparison with a non-OrderedSet returns

not self.isdisjoint(other)

but this returns False when comparing empty sets. I think the following should return True, not False:

OrderedSet([]) == set([])
Don Sawatzky13 years, 6 months ago # |flag

I used this OrderedSet in a chain of functions processing lists. I soon found it was bogging down the calculations. I studied the code and find it is overloaded with Python features. For my purpose, the following simpler function runs 4 times faster.

def OrderedSet(alist):

    """ Creates an ordered set from a list of tuples or other hashable items """    mmap = {} # implements hashed lookup    oset = [] # storage for set    for item in alist:            #Save unique items in input order            if item not in mmap:                    mmap[item] = 1                    oset.append(item)    return oset
Carlos Martín13 years, 1 month ago # |flag

I've create a python package for this recipe and upload to Pypi as 'oset'. Code onhttp://gitorious.org/sleipnir/python-oset. It also works on python 2.5.

@Raymond: If you are interested in maintain this, it's all yours :)

Oren Zomer12 years, 3 months ago # |flag

Hello Raymond,

I created an MIT Licensed project that is using your OrderedSet recipe.I've added the required MIT License comment at the beginning:http://pypsifas.hg.sourceforge.net/hgweb/pypsifas/pypsifas/file/7bfaf2ed308c/psifas/datatypes/ordered_set.py

If you have any problem with that, please let me know.

Oren Zomeroren.zomer@gmail.com

Pascal Lamblin11 years, 4 months ago # |flag

I experienced memory problems (objects were not garbage-collected) when using this recipe, but the one based on weakref worked better.

The __del__ method is not guaranteed to be called when the set is not needed, it will only be called during the garbage collection phase, if the set is ever garbage-collected. Moreover, reference cycles can actually be made worse by the addition of a __del__ method:http://docs.python.org/2/library/gc.html#gc.garbage

Pascal Lamblin11 years, 4 months ago # |flag

For the record, removing the __del__ method actually got rid of the memory leak I was experiencing, at least on Python 2.7.

Grant Jenks8 years, 7 months ago # |flag

You may also want to check out theSortedContainers package. It's a pure-Python and fast implementation of SortedList, SortedDict, andSortedSet data types. "Sorted" isn't the same as "ordered" but it's sometimes what you actually want. There's also extensiveperformance benchmarks with comparisons.

Created byRaymond HettingeronThu, 19 Mar 2009(MIT)
Python recipes (4591)
Raymond Hettinger's recipes (97)
HongxuChen's Fav (39)

Required Modules

Other Information and Tasks

 

Accounts

Code Recipes

Feedback & Information

ActiveState

Privacy Policy |Contact Us |Support

© 2024 ActiveState Software Inc. All rights reserved. ActiveState®, Komodo®, ActiveState Perl Dev Kit®, ActiveState Tcl Dev Kit®, ActivePerl®, ActivePython®, and ActiveTcl® are registered trademarks of ActiveState. All other marks are property of their respective owners.

 x  

[8]ページ先頭

©2009-2026 Movatter.jp