我有一个问题在python文档中并不是很清楚(https://docs.python.org/2/library/stdtypes.html#set.intersection).
使用set.intersection时,结果集包含当前集或其他对象?如果两个对象具有相同的值但在内存中是不同的对象.
我使用它来比较先前从文件中提取的提取与来自互联网的新提取.两者都有一些类似的对象,但我想更新旧的.或者可能有一个更简单的替代方案来实现这一目标?如果实现集合,我会容易得多__getitem__
.
oldApsExtract = set() if (os.path.isfile("Apartments.json")): with open('Apartments.json', mode='r') as f: oldApsExtract = set(jsonpickle.decode(f.read())) newApsExtract = set(getNewExtract()) updatedAps = oldApsExtract.intersection(newApsExtract) deletedAps = oldApsExtract.difference(newApsExtract) newAps = newApsExtract.difference(oldApsExtract) for ap in deletedAps: ap.mark_deleted() for ap in updatedAps: ap.update() saveAps = list(oldApsExtract) + list(newAps) with open('Apartments.json', mode='w') as f: f.write(jsonpickle.encode(saveAps))
Padraic Cunn.. 6
如果集合与b中的交叉元素的大小相同,则使用的对象会有所不同,如果b具有更多元素,则返回a中的对象:
i = "$foobar" * 100 j = "$foob" * 100 l = "$foobar" * 100 k = "$foob" * 100 print(id(i), id(j)) print(id(l), id(k)) a = {i, j} b = {k, l, 3} inter = a.intersection(b) for ele in inter: print(id(ele))
输出:
35510304 35432016 35459968 35454928 35510304 35432016
现在当它们大小相同时:
i = "$foobar" * 100 j = "$foob" * 100 l = "$foobar" * 100 k = "$foob" * 100 print(id(i), id(j)) print(id(l), id(k)) a = {i, j} b = {k, l} inter = a.intersection(b) for ele in inter: print(id(ele))
输出:
35910288 35859984 35918160 35704816 35704816 35918160
有相关部分的来源.该生产线if (PySet_GET_SIZE(other) > PySet_GET_SIZE(so))
,正比较的结果似乎决定哪些对象遍历和哪些对象习惯.
if (PySet_GET_SIZE(other) > PySet_GET_SIZE(so)) { tmp = (PyObject *)so; so = (PySetObject *)other; other = tmp; } while (set_next((PySetObject *)other, &pos, &entry)) { key = entry->key; hash = entry->hash; rv = set_contains_entry(so, key, hash); if (rv < 0) { Py_DECREF(result); return NULL; } if (rv) { if (set_add_entry(result, key, hash)) { Py_DECREF(result); return NULL; }
如果传递的对象不是set,那么同样不是真的,并且长度与使用iterable中的对象无关:
it = PyObject_GetIter(other); if (it == NULL) { Py_DECREF(result); return NULL; } while ((key = PyIter_Next(it)) != NULL) { hash = PyObject_Hash(key); if (hash == -1) goto error; rv = set_contains_entry(so, key, hash); if (rv < 0) goto error; if (rv) { if (set_add_entry(result, key, hash)) goto error; } Py_DECREF(key);
当你传递一个迭代的,首先它可能是一个迭代器,所以你不可能不消耗检查大小,如果你通过一个名单,然后查找将0(n)
是很有意义的,只是遍历可迭代中传递,相反,如果你有一组1000000
元素和一个元素,10
检查是否10
在集合中是否有意义,1000000
而不是检查1000000
您的集合中是否有任何一个,10
因为查找应该是0(1)
平均的,因此它意味着线性传递超过10对线性传递超过1000000个元素.
如果你看一下wiki.python.org/moin/TimeComplexity,就会备份:
平均情况 - >交叉点s&t O(min(len(s),len(t))
最坏情况 - > O(len(s)*len(t))O(len(s)*len(t))
如果t不是一组,则将"min"替换为"max"
因此,当我们传递一个iterable时,我们应该始终从b获取对象:
i = "$foobar" * 100 j = "$foob" * 100 l = "$foobar" * 100 k = "$foob" * 100 print(id(i), id(j)) print(id(l), id(k)) a = {i, j} b = [k, l, 1,2,3] inter = a.intersection(b) for ele in inter: print(id(ele))
你从b获得对象:
20854128 20882896 20941072 20728768 20941072 20728768
如果你真的想要决定你保留哪些对象,那么就进行迭代并自己查找你想要的任何东西.
如果集合与b中的交叉元素的大小相同,则使用的对象会有所不同,如果b具有更多元素,则返回a中的对象:
i = "$foobar" * 100 j = "$foob" * 100 l = "$foobar" * 100 k = "$foob" * 100 print(id(i), id(j)) print(id(l), id(k)) a = {i, j} b = {k, l, 3} inter = a.intersection(b) for ele in inter: print(id(ele))
输出:
35510304 35432016 35459968 35454928 35510304 35432016
现在当它们大小相同时:
i = "$foobar" * 100 j = "$foob" * 100 l = "$foobar" * 100 k = "$foob" * 100 print(id(i), id(j)) print(id(l), id(k)) a = {i, j} b = {k, l} inter = a.intersection(b) for ele in inter: print(id(ele))
输出:
35910288 35859984 35918160 35704816 35704816 35918160
有相关部分的来源.该生产线if (PySet_GET_SIZE(other) > PySet_GET_SIZE(so))
,正比较的结果似乎决定哪些对象遍历和哪些对象习惯.
if (PySet_GET_SIZE(other) > PySet_GET_SIZE(so)) { tmp = (PyObject *)so; so = (PySetObject *)other; other = tmp; } while (set_next((PySetObject *)other, &pos, &entry)) { key = entry->key; hash = entry->hash; rv = set_contains_entry(so, key, hash); if (rv < 0) { Py_DECREF(result); return NULL; } if (rv) { if (set_add_entry(result, key, hash)) { Py_DECREF(result); return NULL; }
如果传递的对象不是set,那么同样不是真的,并且长度与使用iterable中的对象无关:
it = PyObject_GetIter(other); if (it == NULL) { Py_DECREF(result); return NULL; } while ((key = PyIter_Next(it)) != NULL) { hash = PyObject_Hash(key); if (hash == -1) goto error; rv = set_contains_entry(so, key, hash); if (rv < 0) goto error; if (rv) { if (set_add_entry(result, key, hash)) goto error; } Py_DECREF(key);
当你传递一个迭代的,首先它可能是一个迭代器,所以你不可能不消耗检查大小,如果你通过一个名单,然后查找将0(n)
是很有意义的,只是遍历可迭代中传递,相反,如果你有一组1000000
元素和一个元素,10
检查是否10
在集合中是否有意义,1000000
而不是检查1000000
您的集合中是否有任何一个,10
因为查找应该是0(1)
平均的,因此它意味着线性传递超过10对线性传递超过1000000个元素.
如果你看一下wiki.python.org/moin/TimeComplexity,就会备份:
平均情况 - >交叉点s&t O(min(len(s),len(t))
最坏情况 - > O(len(s)*len(t))O(len(s)*len(t))
如果t不是一组,则将"min"替换为"max"
因此,当我们传递一个iterable时,我们应该始终从b获取对象:
i = "$foobar" * 100 j = "$foob" * 100 l = "$foobar" * 100 k = "$foob" * 100 print(id(i), id(j)) print(id(l), id(k)) a = {i, j} b = [k, l, 1,2,3] inter = a.intersection(b) for ele in inter: print(id(ele))
你从b获得对象:
20854128 20882896 20941072 20728768 20941072 20728768
如果你真的想要决定你保留哪些对象,那么就进行迭代并自己查找你想要的任何东西.