Array Vector

An array vector is a special type of vector used to store variable-length two-dimensional arrays. This article describes how to create array vectors and read from and write to them.

Create an Array Vector

The C++ API provides two ways to create an array vector.

Method 1

Create an array vector by providing the index and value arrays. The syntax is as follows:

static Vector* createArrayVector(VectorSP index, VectorSP value);

For details about index and value, see arrayVector.

Sample code

VectorSP index = Util::createVector(DT_INT, 0);
int indexData[3]{3, 6, 9};
index->appendInt(indexData, 3);
VectorSP value = Util::createVector(DT_LONG, 0);
long long valueData[9]{1, 2, 3, 1, 2, 3, 1, 2, 3};
value->appendLong(valueData, 9);
VectorSP v2 = Util::createArrayVector(index, value);
std::cout << v2->getString() << std::endl;            
//output: [[1,2,3],[1,2,3],[1,2,3]]

Method 2

Create an array vector by specifying the type.

static Vector* createArrayVector(DATA_TYPE type, INDEX size, INDEX capacity = 0, bool fast = true, int extraParam = 0, void *data = NULL, INDEX *pindex = NULL, bool containNull = false);

Parameters

type: The element type, such as DT_LONG_ARRAY or DT_INT_ARRAY.

size: The initial size.

capacity: The capacity allocated during construction. Setting the capacity appropriately can improve insertion performance.

fast: A reserved parameter that is currently unused.

extraParam: Used when creating a DECIMAL array vector to pass the DECIMAL scale.

data: If initial elements are provided, use data to pass the contents of the value array. You do not need to free this memory manually. The Vector destructor releases it automatically with delete[].

pindex: If initial elements are provided, use pindex to pass the contents of the index array. You do not need to free this memory manually. The Vector destructor releases it automatically with delete[].

containNull: If you pass data, this parameter specifies whether data contains null values. true indicates that it does; the default is false, which indicates that it does not.

Sample code

int *indexData = new int[3]{3, 6, 9};
long long *valueData = new long long[9]{1, 2, 3, 1, 2, 3, 1, 2, 3};
VectorSP v3 = Util::createArrayVector(DT_LONG_ARRAY, 3, 3, true, 0, valueData, indexData);
std::cout << v3->getString() << std::endl;
// output: [[1,2,3],[1,2,3],[1,2,3]]

Append Data

Use the append method to add data. Append value to the end of the array vector, where value can be a vector or an array of vectors. The syntax is as follows:

bool append(const ConstantSP& value);

Sample code

long long data[3]{1, 2, 3};
VectorSP subv1 = Util::createVector(DT_LONG, 0);
subv1->appendLong(data, 3);
v3->append(subv1);
std::cout << v3->getString() << std::endl;         //[[1,2,3],[1,2,3],[1,2,3],[1,2,3]]
VectorSP v4 = ConstantSP(v3)->getValue();
v3->append(v4);
std::cout << v3->getString() << std::endl;         //[[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3]]

Read Data

The C++ API provides two ways to read data from an array vector.

Method 1

Use the get method to retrieve data by index. The syntax is as follows:

ConstantSP get(INDEX index) const;

Sample code

VectorSP subv2 = v3->get(2);
std::cout << subv2->getString() << std::endl;
// [1,2,3]
Note:
This method creates a new array each time you call it, which involves additional memory allocation and deallocation. If you need better read performance, we recommend using Method 2.

Method 2

Retrieve the value and index arrays, and then use them to access the data. The syntax is as follows:

ConstantSP getSourceValue();
ConstantSP getSourceIndex();

Sample code

int *indexData = new int[3]{3, 9, 11};
long long *valueData = new long long[11]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
VectorSP v3 = Util::createArrayVector(DT_LONG_ARRAY, 3, 3, true, 0, valueData, indexData);
std::cout << v3->getString() << std::endl;


int maxLength = 10;
std::vector<long long> element(maxLength);
VectorSP value = dynamic_cast<FastArrayVector*>(v3.get())->getSourceValue();
VectorSP index = dynamic_cast<FastArrayVector*>(v3.get())->getSourceIndex();

const long long* valueBuf = value->getLongConst(0, value->size(), nullptr);
const int* indexBuf = index->getIndexConst(0, index->size(), nullptr);
int startIndex = 0;
int length = 0;
for(int i = 0; i < v3->size(); ++i){
    length = indexBuf[i] - startIndex;
    memcpy(element.data(), valueBuf + startIndex, length * sizeof(long long));
    std::cout << "the " << i << " element: ";
    for(int j = 0; j < length; ++j) {
        std::cout << element[j] << " ";
    }
    std::cout << std::endl;
    startIndex = indexBuf[i];
}

Complete Example

Create a table object with an array vector column, and write data to it.

#include "DolphinDB.h"
#include "Util.h"
#include <iostream>
#include <vector>

using namespace dolphindb;
using namespace std;

int main() {
    try {
        // 1. Define the table schema
        int rowNum = 3;
        int elementsPerRow = 3;
        vector<string> colNames = { "id", "value" };
        vector<DATA_TYPE> colTypes = { DT_INT, DT_DOUBLE_ARRAY };

 // 2. Create an index vector
        VectorSP indexVector = Util::createVector(DT_INDEX, rowNum, rowNum);
        INDEX* pindex = indexVector->getIndexArray();

        int cumulative = 0;
        for (int i = 0; i < rowNum; ++i) {
            cumulative += elementsPerRow;
            pindex[i] = cumulative;
        }

 // 3. Create a value vector
        VectorSP valueVector = Util::createVector(DT_DOUBLE, rowNum * elementsPerRow, rowNum * elementsPerRow);

        int valueIndex = 0;
        for (int i = 0; i < rowNum; ++i) {
            for (int j = 0; j < elementsPerRow; ++j) {
                valueVector->setDouble(valueIndex++, i * 3 + j + 0.1);
            }
        }

 // 4. Create a array vector
        VectorSP arrayVectorCol = Util::createArrayVector(indexVector, valueVector);

        // 5. Create the id column
        VectorSP idCol = Util::createVector(DT_INT, rowNum, rowNum);
        for (int i = 0; i < rowNum; ++i) {
            idCol->setInt(i, i);
        }

        // 6. Create the table
        vector<ConstantSP> cols = { idCol, arrayVectorCol };
        ConstantSP table = Util::createTable(colNames, cols);

        // 7. Connect and upload
        DBConnection conn;
        conn.connect("127.0.0.1", 8848);
        conn.login("admin", "123456", false);
        conn.upload("myArrayVectorTable", table);

        // 8. Verify
        ConstantSP result = conn.run("select * from myArrayVectorTable;");
        cout << "------ Data Verification ------" << endl;
        cout << result->getString() << endl;

        conn.close();

    }
    catch (const std::exception& e) {
        cout << "Error: " << e.what() << endl;
        return -1;
    }

    return 0;
}