2011-04-23 106 views
1

我的工作对这个职位所带来的问题:Fast way to remove a few items from a list/queue在C中实现一个简单的python函数很简单吗?

基本上所有我想要做的就是实现一个for循环C中的for循环需要访问一台发电机,并能够删除数组中的元素(并增加一个整数)。我身上的某些东西告诉我这很难,但另一部分则表示可以在几分钟内处理。我没有编写高级C的经验(我已经编写了微控制器的代码),而且ctypes和其他c-> python的教程看起来像是解决了更多难题。

def forfilt(): 
    marked = (i for i, x in enumerate(b) if tokeep(x)) 
    shift = 0 
    for n in marked: 
     del b[n - shift] 
     shift += 1 

我问两个问题:

  • 是这样难吗?

  • 你有任何指针/希望自己编写的代码? :D

这对我来说似乎是一个相当重要的问题。我不知道有什么办法可以快速完成原始问题的要求。我想如果你知道答案的话,那么这个问题就是无效的。

+1

为什么你认为C会比原生Python代码更快? – 2011-04-23 04:53:33

+0

,因为for循环的速度非常慢,而且这无法通过压缩来解决。 – 2011-04-23 04:56:20

+1

为什么不使用Cython或者ShedSkin? – joaquin 2011-04-23 08:14:16

回答

3

如果你需要的是消除循环开销那么就足够了用Cython(pip install cython)来定义的类型循环变量。下面是用Cython delitems.pyx修改remove_inplace_senderle2()

#cython: boundscheck=False, wraparound=False 
import cython 

@cython.locals(end=cython.Py_ssize_t, i=cython.Py_ssize_t) 
def remove_inplace_senderle2(L, keep): 
    end = 0 
    for i in range(len(L)): 
     x = L[end] = L[i] 
     if keep(x): 
      end += 1 

    del L[end:] 

for i in range(len(L))转化为经典的C-循环:for (i=0; i < L_length; ++i)其开销由keep()的函数调用的开销相形见绌。

注:上述功能可以是纯Python比L = filter(keep, L)(或listcomp)慢。

即使简单的例子见gcd() function用Cython如何可以编译和使用。

+0

嘿,非常感谢。这正是我所问的问题,解决方案似乎很简单和pythonic:D – 2011-04-25 17:28:23

2

这取决于如何简单也很简单。是的,只要输入是一个数组,就可以将此特定函数写成就地存储器移动。

size_t for_filt(my_struct *b, size_t n) { 
    my_struct *src_pen, *dst_pen; 

    for (src_pen = dst_pen = b; 
      src_pen != b + n; 
      ++ src_pen) { 
     if (tokeep(src_pen)) { 
      memmove(dst_pen ++, src_pen, sizeof (my_struct)); 
     } 
    } 

    return dst_pen - b; /* return number of elements in resulting array */ 
} 

的C++标准库降低上述功能到一衬垫:

n = std::remove_if(b, b+n, std::not1(tokeep)) - b; 

的功能将与结构的工作除了阵列,但n = … - b;是阵列特异性的。

2

写作对CPython的C-API的C代码相当比写的C代码不支持这样的API的更加愉快。然而,它主要是建立和连接过程,并完成所有这些可能相当乏味的事情。一旦你有了一个C扩展,添加它并不是太困难(尽管在Python级别上正确暴露事物并确保所有引用计数是正确的仍然有一些摆弄。

其他静态编译工具,如用Cython类似从相对较高的安装成本挨得到编译扩展摆在首位的工作,但更容易使用一旦已经到位。

关于你的具体问题,通过比较列表解析的方法来filter内置(或Py3k等同,functools.filter)你链接的问题的海报有已经证明丢弃循环代码分解成的影响C本地循环是内置迭代和缩减功能的主要优点之一,如sum,any,all,mapfilter

移除Python层面环路开销的是在两种方法的性能最测量〜10%的差异的(列表理解VS滤波器呼叫)可能负责。