Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/codeigniter/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 肾盂可吸收差_Python_Python 2.7 - Fatal编程技术网

Python 肾盂可吸收差

Python 肾盂可吸收差,python,python-2.7,Python,Python 2.7,我编写了一些代码来查找一个iterable中的所有项,而不是另一个iterable中的所有项,反之亦然。我最初使用的是内置的集合差异,但计算速度相当慢,因为每个集合中存储了数百万项。因为我知道最多会有几千个差异,所以我写了以下版本: def differences(a_iter, b_iter): a_items, b_items = set(), set() def remove_or_add_if_none(a_item, b_item, a_set, b_set):

我编写了一些代码来查找一个iterable中的所有项,而不是另一个iterable中的所有项,反之亦然。我最初使用的是内置的集合差异,但计算速度相当慢,因为每个集合中存储了数百万项。因为我知道最多会有几千个差异,所以我写了以下版本:

def differences(a_iter, b_iter):
    a_items, b_items = set(), set()

    def remove_or_add_if_none(a_item, b_item, a_set, b_set):
        if a_item is None:
            if b_item in a_set:
                a_set.remove(b_item)
            else:
                b_set.add(b)

    def remove_or_add(a_item, b_item, a_set, b_set):
        if a in b_set:
            b_set.remove(a)
            if b in a_set:
                a_set.remove(b)
            else:
                b_set.add(b)
            return True
        return False

    for a, b in itertools.izip_longest(a_iter, b_iter):
        if a is None or b is None:
            remove_or_add_if_none(a, b, a_items, b_items)
            remove_or_add_if_none(b, a, b_items, a_items)
            continue

        if a != b:
            if remove_or_add(a, b, a_items, b_items) or \
               remove_or_add(b, a, b_items, a_items):
                continue
            a_items.add(a)
            b_items.add(b)

    return a_items, b_items

但是,上面的代码似乎不太符合python,因此我正在寻找替代方案或改进建议。

我认为您的代码已损坏-请使用
[1,1]
[1,2]
进行尝试,您会发现
1
在一组中,而不是在另一组中

> print differences([1,1],[1,2])                                                   
(set([1]), set([2]))
您可以将其追溯到
的效果,如果a!=b
test(假设在简单的集合差异中不存在排序)


如果没有这个测试,它可能会丢弃许多值,我认为您的方法不会比内置集更快。这个论点是这样的:你真的需要在内存中创建一个集合来保存所有的数据(你的错误是因为没有这样做)。朴素的集合方法创建两个集合。因此,您所能做的最好的事情就是节省一半的时间,并且您还必须使用python来完成可能是高效的c代码。

我认为python集操作将是您从标准库中获得的最佳性能

问题可能在于您选择的特定实现,而不是数据结构和伴随操作本身。这里有一个替代实现,它应该可以为您提供更好的性能

对于序列较大的序列比较任务,尽可能避免将组成序列的对象放入用于比较的容器中——最好使用索引。如果序列中的对象是无序的,则对它们进行排序

例如,我使用数字python库来执行以下任务:

# a, b are 'fake' index arrays of type boolean
import numpy as NP
a, b  = NP.random.randint(0, 2, 10), NP.random.randint(0, 2, 10)
a, b = NP.array(a, dtype=bool), NP.array(b, dtype=bool)

# items a and b have in common:
NP.sum(NP.logical_and(a, b))

# the converse (the differences)
NP.sum(NP.logical_or(a, b))

下面是一个更具python风格的解决方案:

a, b = set(a_iter), set(b_iter)

return a - b, b - a
Pythonic并不意味着快速,而是优雅易读

下面是一个可能更快的解决方案:

a, b = set(a_iter), set(b_iter)

# Get all the candidate return values
symdif = a.symmetric_difference(b)

# Since symdif has much fewer elements, these might be faster
return symdif - b, symdif - a
现在,关于用Python编写自定义“快速”算法而不是使用内置操作:这是一个非常糟糕的主意

set操作符经过了大量优化,并用C编写,通常比Python快得多。 您可以用C(或Cython)编写算法,但请记住Python的集合算法是由世界级的天才编写和优化的。 除非你非常擅长优化,否则这可能是不值得的。另一方面,如果你确实设法大大加快了速度,请分享你的代码;我打赌它有机会进入Python本身

要获得更现实的方法,请尝试取消对Python代码的调用。例如,如果您的对象具有自定义相等运算符,请找出删除该运算符的方法


但是不要抱太大的希望。处理数百万条数据总是需要很长时间。我不知道你在哪里使用这个,但也许让计算机忙上一分钟比花时间优化集合算法更好?

你的集合比内置的集合差快多少?