Find a cell in a 2D extensor table based on colum values

98 Views Asked by At

I want to read one cell of a 2D xtensor table based on a matching cell in a column in the table.

Conside a 2D table of elements of type std::string:

+-----+---+---+---+
| fee | I | J | K |
+-----+---+---+---+
| fie | L | M | N |
+-----+---+---+---+
| fo  | O | P | Q |
+-----+---+---+---+
| fum | R | S | T |
+-----+---+---+---+

I want to read the value of the 3rd cell in the row where the first column == 'fo', ie 'P'

Searches on the internet suggest code that uses the function xt::keep() which seems not to be implemented. How do I carry this out using xt functions that are actually implemented?

2

There are 2 best solutions below

4
On

You can check where in your array is there an element equal to "fo". The result, in this case would be the index {2, 0}. Than you can use the first element of that index (2) and the desired column index (2) and get a view of the array in the desired position.

Like this:

#include <xtensor/xtensor.hpp>
#include <xtensor/xio.hpp>
#include "xtensor/xview.hpp"

int main()
{
    xt::xarray<std::string> arr{{"fee", "i", "j", "k"},
                                {"fie", "l", "m", "n"},
                                {"fo", "o", "p", "q"},
                                {"fum", "r", "s", "t"}};

    auto indices = xt::where(xt::equal(arr, std::string("fo"))) // indices = {{2}, {0}}
    auto result = xt::view(arr, xt::keep(indices[0]), xt::keep(2)) // result = {"p"}
    std::cout << result << std::endl;
    return 0;
}
12
On

In addition to the answer of @TaiguaraTupinambás I would like to suggest you not to use xt::view at all when you want to get a specific element from an array (or "matrix" or "table" in your 2d case). For your example I would do:

#include <xtensor/xtensor.hpp>
#include <xtensor/xio.hpp>

int main()
{
    xt::xtensor<std::string, 2> arr =
        {{"fee", "I", "J", "K"},
         {"fie", "L", "M", "N"},
         {"fo" , "O", "P", "Q"},
         {"fum", "R", "S", "T"}};

    auto indices = xt::from_indices(xt::argwhere(xt::equal(arr, std::string("fo"))));
    auto row = indices(0, 0);
    std::cout << arr(row, 2) << std::endl;
    return 0;
}

Notice that row is simply an index (of type size_t). Now arr(row, 2) is a reference (of type std::string&) to the element you were looking for. This is I think cleaner than using xt::view in this case, and it will turn out to be much faster too.