检查对象中是否存在项目并获取项目

时间:2016-02-15 19:20:14

标签: python optimization

我需要检查某个对象中是否存在某些item(可以正常工作:listsetdictcollection。 ..)并从该对象获取数据。 我发现的最好方法是构建一个dict keyvalue

known={}
for item in list:
    if item in known:
        item = known[item]
    else
        known[item] = item
    foo(item)

list的另一种方式(但非常慢):

known=[]
for item in list:
    if not item in known:
        known.insert(0, item)
    else:
        item = known[known.index(item)]
    foo(item)

最后一个有set():

known = set()
for item in list:
    if item in known:
        item = next(i for i in known if i == item)
    else:
        known.add(item)
    foo(item)

看起来很荒谬吗?我想不出一个简单的方法,没有丑陋的黑客,性能损失和/或内存使用。

我正在构建这些可恶的原因而不是:

for item in list:
    foo(item)

items list内的a == b是大字符串,其中大多数是相同的(在a is b的感觉中),但不相同,(foo()意义上的$a0 1}})。我需要节省内存使用。所以我想在主对象中添加一个唯一的项目,并只将该项目的引用发送到50

如果有良好的性能/内存/可读性妥协,我怎么能这样做?

3 个答案:

答案 0 :(得分:2)

如果我理解正确,那么您正在寻找一种方法来映射比较等于单个唯一实例的字符串。在这种情况下,请考虑使用intern内置函数。 intern将字符串放入Python的内部“interned string”映射中,并返回该字符串的唯一实例。只要您需要一个唯一的实例,就可以在字符串上调用intern

演示:

>>> s1 = "a"
>>> s2 = "b"
>>> s3 = "ab"
>>> s4 = s1 + s2
>>> id(s3)
4300082912
>>> id(s4)
4300081472
>>> s5 = intern(s3)
>>> id(s5)
4300082912
>>> id(intern(s4))
4300082912

演示2(Python 2):

>>> arr = [str(x // 2) for x in range(1000, 1010)]
>>> arr
['500', '500', '501', '501', '502', '502', '503', '503', '504', '504']
>>> map(id, arr) # all strings in arr are distinct
[4300081512, 4300081552, 4300081592, 4300081672, 4300081712, 4300081752, 4300081792, 4300081832, 4300081872, 4300081912]
>>> arr2 = map(intern, arr)
>>> arr2
['500', '500', '501', '501', '502', '502', '503', '503', '504', '504']
>>> map(id, arr2) # equal strings are identical now
[4300079632, 4300079632, 4300081592, 4300081592, 4300081712, 4300081712, 4300081792, 4300081792, 4300081872, 4300081872]

答案 1 :(得分:0)

使用dict很好,但您可以使用setdefault。演示设置:

>>> items = [str(i//2) for i in range(6)]
>>> items
['0', '0', '1', '1', '2', '2']
>>> list(map(id, items))
[55450176, 55450240, 55450208, 55450272, 55450304, 55450336]

为每个值使用第一个对象:

>>> firsts = map({}.setdefault, items, items)

演示它有效:

>>> list(map(id, firsts))
[55450176, 55450176, 55450208, 55450208, 55450304, 55450304]

答案 2 :(得分:0)

如何使用套装:

fn

输出:

lst = ['huge string1', 'huge string1','huge string1','huge string1', 'huge string2', 'huge string2','huge string2','huge string2']
print(lst)
print(set(lst))