6

重複の可能性:
Python:セットからアイテムを取得する

次のコードを検討してください。

>>> 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あるためですが、それは別のオブジェクトです。

私が欲しいのは与えられたものitem1から得ることです。snew_items

私が思いついた解決策の1つは簡単ですが、あまり効率的ではありません。

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()

これも:

 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

これが問題になる場合は、Windows7でPython2.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)
4

2 に答える 2

12

を使用しないでくださいsetdictある値をそれ自体にマップするを使用するだけです。あなたの場合、それはマップします:

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

したがって、に等しいものitem1はすべてにありdますが、値はitem1それ自体です。そして、それは線形時間よりもはるかに優れています;-)

PSあなたの質問の意図を正しく理解したと思います。そうでない場合は、それを明確にしてください。

于 2012-04-30T12:45:13.000 に答える
2

O(1)ルックアップオブジェクトID(同等性だけでなく)高速セット操作(セット操作を実行するたびに新しいセットを作成する必要がない)が絶対に必要な場合、かなり簡単なアプローチの1つは、との両方を使用することです。 。dict_ set同期を維持するには、両方の構造を維持する必要がありますが、これにより、O(1)アクセスを維持できます(定数係数が大きくなります)。(そして多分これはあなたがあなたの編集であなたの「現在非常に不完全である将来の解決策」で向かっているものです。)

ただし、使用しているデータの量や、発生しているパフォーマンスの問題の種類については言及していません。だから私はあなたが本当にこれをする必要があるとは確信していません。dict必要に応じてset作成したりset、線形ルックアップを使用したりすると、すでに十分に高速である可能性があります。

于 2012-04-30T14:27:00.360 に答える