Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to iterate throught C++ sets in Cython?

I am optimizing python code with Cython. A set in C++ is storing all my results, and I do not know how to access the data to move it into a Python object. The structure must be a set. I cannot change it to a vector, list, etc.

I know how to do this in Python and C++, but not in Cython. How are iterators retrieved in Cython? I get STL containers via libcpp.STLContainer as in

from libcpp.vector cimport vector

But, I don't know how iterators work in Cython. What do I need to import? And, is there any change in syntax for using iterators compared to how they work in C++?

like image 434
ReverseFlow Avatar asked Mar 22 '15 22:03

ReverseFlow


People also ask

Can you iterate through sets in Python?

There are numerous ways that can be used to iterate over a Set. Some of these ways provide faster time execution as compared to others. Some of these ways include, iterating using for/while loops, comprehensions, iterators and their variations. Let's see all the different ways we can iterate over a set in Python.

Can you iterate through sets?

There is no way to iterate over a set without an iterator, apart from accessing the underlying structure that holds the data through reflection, and replicating the code provided by Set#iterator...

What is set () in Python?

set() method is used to convert any of the iterable to sequence of iterable elements with distinct elements, commonly called Set. Parameters : Any iterable sequence like list, tuple or dictionary. Returns : An empty set if no element is passed.

How to iterate through a set in Python?

The easiest way to loop over a set in Python is with a standard for loop. Even though we cannot access the items of a set by index directly, we can still iterate through the set with a loop. Below is an example of how to iterate through a set in Python using a for loop. set = {1,2,3} for x in set: print x #Output: 1 2 3

How to iterate over a set in C++?

Method #1: Iterating over a set using simple for loop. Method #2: Iterating over a set using enumerated for loop. Method #3: Iterating over a set as indexed list. Method #4: Iterating over a set using comprehension and list constructor/initializer. Method #5: Iterating over a set using comprehension. Method #7: Iterating over a set using iterator.

How do you loop through a set in Python?

Looping over sets is easy in Python and is similar to iterating through other objects in Python. The easiest way to loop over a set in Python is with a standard for loop. Even though we cannot access the items of a set by index directly, we can still iterate through the set with a loop.

What is a set in Python?

In Python, Set is an unordered collection of data type that is iterable, mutable and has no duplicate elements. There are numerous ways that can be used to iterate over a Set.


2 Answers

Cython should automatically convert a c++ set to a python set when needed, however if you really do need to use iterators on the c++ object you can do that as well.

If we make a very simple example where we construct a set in c++

libset.cc

#include <set>

std::set<int> make_set()
{
    return {1,2,3,4};
}

libset.h

#include <set>

std::set<int> make_set();

We can then write the cython wrapper for this code as, where I've given an example of how to iterate through the set in a nice pythonic way (which uses the c++ iterators in the background) and an example of how to do it directly with iterators.

pyset.pyx

from libcpp.set cimport set
from cython.operator cimport dereference as deref, preincrement as inc

cdef extern from "libset.h":
    cdef set[int] _make_set "make_set"()

def make_set():
    cdef set[int] cpp_set = _make_set()

    for i in cpp_set: #Iterate through the set as a c++ set
        print i

    #Iterate through the set using c++ iterators.
    cdef set[int].iterator it = cpp_set.begin()
    while it != cpp_set.end():
        print deref(it)
        inc(it)

    return cpp_set    #Automatically convert the c++ set into a python set

This can then be compiled with a simple setup.py

setup.py

from distutils.core import setup, Extension
from Cython.Build import cythonize

setup( ext_modules = cythonize(Extension(
            "pyset",
            sources=["pyset.pyx", "libset.cc"],
            extra_compile_args=["-std=c++11"],
            language="c++"
     )))
like image 179
Simon Gibbons Avatar answered Oct 05 '22 07:10

Simon Gibbons


Very nice answer by Simon. I had to do this for a C++ map to python dict. Here's my rough cython code for the map case:

from libcpp.map cimport map

# code here for _make_map() etc.

def get_map():
    '''
    get_map()
    Example of cython interacting with C++ map.

    :returns: Converts C++ map<int, int> to python dict and returns the dict
    :rtype: dict
    '''
    cdef map[int, int] cpp_map = _make_map()

    pymap = {}
    for it in cpp_map: #Iterate through the c++ map
        pymap[it.first] = it.second

    return pymap
like image 22
Al Conrad Avatar answered Oct 05 '22 05:10

Al Conrad