2012-04-30 4 views
6

可能性の重複:
Python: Retrieve items from a setO(1)時間にセットからアイテムを取得する方法はありますか?

次のコードを考えてみましょう:

>>> item1 = (1,) 
>>> item2 = (2,) 
>>> s = set([item1, item2]) 
>>> s 
set([(2,), (1,)]) 
>>> new_item = (1,) 
>>> new_item in s 
True 
>>> new_item == item1 
True 
>>> new_item is item1 
False 

をだから、その項目の1に相当しますので、new_itemsであるが、それはあります別のオブジェクト。

item1sからnew_itemに、sになります。私が出ている

一つの解決策は、非常に効率的に簡単ではなく、次のとおりです。

def get_item(s, new_item): 
    for item in s: 
     if item == new_item: 
      return item 

>>> get_item(s, new_item) is new_item 
False 
>>> get_item(s, new_item) is item1 
True 

別の解決策は、より効率的なようだが、実際には動作しません:

def get_item_using_intersection1(s, new_item): 
    return set([new_item]).intersection(s).pop() 

も、この1:

def get_item_using_intersection2(s, new_item): 
    return s.intersection(set([new_item])).pop() 

交差点が未定義の方法で動作するため:

>>> get_item_using_intersection1(s, new_item) is new_item 
True 
>>> get_item_using_intersection1(s, new_item) is item1 
False 

>>> get_item_using_intersection2(s, new_item) is new_item 
True 
>>> get_item_using_intersection2(s, new_item) is item1 
False 

この場合、私はWindows 7でPython 2.7 x64を使用していますが、クロスプラットフォームのソリューションが必要です。


ありがとうございます。私は、次の一時的な解決策を思い付いた:

(今非常に不完全である)以下の溶液を用いて、将来的に置き換えられます
class SearchableSet(set): 

    def find(self, item): 
     for e in self: 
      if e == item: 
       return e 

class SearchableSet(object): 

    def __init__(self, iterable=None): 
     self.__data = {} 
     if iterable is not None: 
      for e in iterable: 
       self.__data[e] = e 

    def __iter__(self): 
     return iter(self.__data) 

    def __len__(self): 
     return len(self.__data) 

    def __sub__(self, other): 
     return SearchableSet(set(self).__sub__(set(other))) 

    def add(self, item): 
     if not item in self: 
      self.__data[item] = item 

    def find(self, item): 
     return self.__data.get(item) 
+1

...あなたが思いついた "非効率的な解決策"は、すでに線形です。 – kennytm

+0

私は彼が*定数*時間を意味すると思う –

+0

@ケニーTM、ありがとう、私は私の質問のタイトルを編集しました。 – utapyngo

答えて

12

setを使用しないでください、そして、 。ちょうどそれ自身にある価値を写像するdictを使用してください。 item1に等しいです

d[item1] = item1 
d[item2] = item2 

だから、何がdに記載されていますが、値はitem1そのものである:あなたのケースでは、それがマッピングされます。そしてそれは線形時間よりもはるかに良い;-)

P.S.私はあなたの質問の意図を正しく理解することを願っています。そうでない場合は、明確にしてください。その後、

+0

ありがとうございます。 'dict'を使うことは可能ですが、技術的には' set'を使うことも可能です(ハッシュで項目を見つけることができる内部メソッドがあると仮定して)。また、set操作を集中的に使用するため、古いコードを書き直したくない。 – utapyngo

+7

@utapyngo:古いコードが間違っていると書き直す方が良いです。 'set'は単にこれに対して設計されたものではなく、より適切なデータ構造を使います。 –

+0

線形時間でのそのようなdictsのinerection、unionと違いを行う方法? – utapyngo

2

あなたは絶対に(新しいセットにあなたがセットの操作をしたいたびに作成することなく)、O(1)検索オブジェクトのアイデンティティ(だけでなく、平等)速い集合演算が必要な場合は、1かなり単純なアプローチは、 a dictsetの両方を使用することです。同期をとるためには両方の構造を維持する必要がありますが、これによりO(1)アクセスを維持することができます(より大きな定数で)。(そして、あなたの編集であなたの "将来の解決策は今は非常に不完全です"とあなたに向かっているのでしょうか?)

しかし、あなたはあなたが作業しているデータ量あなたが持っているパフォーマンス問題の種類だから私はあなたが本当にこれを行う必要があると確信していない。必要なときにを作成してsetを作成するか、またはリニアルックアップを使用してsetを作成することができます。

関連する問題