当前位置:  开发笔记 > 编程语言 > 正文

Python Set Intersection - 返回哪些对象

如何解决《PythonSetIntersection-返回哪些对象》经验,为你挑选了1个好方法。

我有一个问题在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

如果你真的想要决定你保留哪些对象,那么就进行迭代并自己查找你想要的任何东西.



1> Padraic Cunn..:

如果集合与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

如果你真的想要决定你保留哪些对象,那么就进行迭代并自己查找你想要的任何东西.


@husvar,我想如果你正在寻找交叉点,那么迭代更小的集合会更有意义,如果另一个集合只有10个元素,则没有迭代超过10000个元素的点
推荐阅读
郑小蒜9299_941611_G
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有