Are multi-dimensional multi maps possible? - c++

All the examples of multimap, yet to find a multi-dimensional example...
System: Visual Studio 2019, C++. Winapi with no extra libraries
Expected result: stores a multi-dimensional array of key/value pairs. Able to pull up a key pair by specifying parent key pairs (similar to hashes in Perl)
Using multimap instead of map since some of the fields have the same header.
Example of my data:
conversationID(int)
|
ConversationType(wstring)
lineID(int)
|
lineType(wstring)
originalLine(wstring)
taggedLine(wstring)
wordID
|
...
Declare the structure:
#include <map>
multimap< int, multimap <int, multimap <wstring, multimap <wstring, multimap <wstring, multimap<wstring, wstring> > > > > > conversation;
multimap< int, multimap <int, multimap <wstring, multimap <wstring, multimap <wstring, multimap<wstring, wstring> > > > > > ::iterator conversationIt;
Try to store some stuff in it... (error: "no instance of overloaded function")
conversation.insert(make_pair<int,int>(2, 1 make_pair<wstring, wstring>(L"originalLine", line)));
Also tried the following but found that multimap does not support [] insert:
conversation[0][0][L"originalLine"][line];

Based on the tree diagram above, the best approach is a simple multidimensional array.
this allows for duplicate "keys"
mixed variable types can be achieve by using supporting tables (see example below)
Compared to other methods:
map does not allow duplicate keys
multimap. could not get this to work. tried for weeks.
class inheritance. does not link sub branches to branches above. it is just a method for exposing variables and methods without having to duplicate your work.
also looked at multisets, vectors, etc.
note: for a large multidimensional array, you will need to use heap memory.
void conversationArray(LPWSTR line)
{
auto conversation = new int[5][10000][100][50]; // conversationID, lineID, objectID, tagid = tag/text
wstring conversationType[3];
auto lineType = new wstring[5][10000]; // conversationID, lineID = string
wstring text[50];
conversationType[0] = L"chat gui";
lineType[0][0] = L"chat";
conversation[0][0][14][12] = 25;
conversation[0][0][15][12] = 30;
lineType[0][1] = L"chat1";
conversation[0][1][15][12] = 500;
lineType[0][2] = L"chat2";
conversation[0][2][15][12] = 60;
conversationType[1] = L"chat gui1";
lineType[1][0] = L"chat-also";
conversation[1][0][15][12] = 33;
// if tag id = 0 then tag is text
conversation[0][0][14][0] = 0;
conversation[0][0][15][0] = 20;
text[0] = line;
text[20] = L"dog";
// print out
int records = 0;
for (int conversationID = 0; conversationID < 5; conversationID++)
{
//sendToReportWindow(L"conversationID: %d\n", conversationID);
for (int lineID = 0; lineID < 10000; lineID++)
{
//sendToReportWindow(L"lineID:%d\n", lineID);
for (int objectID = 0; objectID < 100; objectID++)
{
//sendToReportWindow(L"objectID:%d\n", objectID);
for (int tagID = 0; tagID < 50; tagID++)
{
if (conversation[conversationID][lineID][objectID][tagID] >= 0)
{
if (tagID > 0)
{
sendToReportWindow(L"conversationID:%d type:%s\n", conversationID, conversationType[conversationID].c_str());
sendToReportWindow(L"lineID:%d type:%s\n", lineID, lineType[conversationID][lineID].c_str());
sendToReportWindow(L"conversation[%d][%d][%d][%d]= %d\n", conversationID, lineID, objectID, tagID, conversation[conversationID][lineID][objectID][tagID]);
sendToReportWindow(L"\n");
}
else
{
sendToReportWindow(L"conversationID:%d type:%s\n", conversationID, conversationType[conversationID].c_str());
sendToReportWindow(L"lineID:%d type:%s\n", lineID, lineType[conversationID][lineID].c_str());
sendToReportWindow(L"conversation[%d][%d][%d][%d] text = %s\n", conversationID, lineID, objectID, tagID, text[conversation[conversationID][lineID][objectID][tagID]].c_str());
sendToReportWindow(L"\n");
}
records++;
}
}
}
}
}
sendToReportWindow(L"records:%d\n", records);
sendToReportWindow(L"\n");
// print all records on a specific branch. all lines for conversation 1, line 0
int conversationID = 1; int lineID = 0;
sendToReportWindow(L"Just print a subset of conversation:%d and Line:%d\n", conversationID, lineID);
for (int objectID = 0; objectID < 100; objectID++)
{
for (int tagID = 0; tagID < 50; tagID++)
{
if (conversation[1][0][objectID][tagID] >= 0)
{
if (tagID > 0)
{
sendToReportWindow(L"conversationID:%d type:%s\n", conversationID, conversationType[conversationID].c_str());
sendToReportWindow(L"lineID:%d type:%s\n", lineID, lineType[conversationID][lineID].c_str());
sendToReportWindow(L"conversation[%d][%d][%d][%d]= %d\n", conversationID, lineID, objectID, tagID, conversation[conversationID][lineID][objectID][tagID]);
sendToReportWindow(L"\n");
}
else
{
sendToReportWindow(L"conversationID:%d type:%s\n", conversationID, conversationType[conversationID].c_str());
sendToReportWindow(L"lineID:%d type:%s\n", lineID, lineType[conversationID][lineID].c_str());
sendToReportWindow(L"conversation[%d][%d][%d][%d] text = %s\n", conversationID, lineID, objectID, tagID, text[conversation[conversationID][lineID][objectID][tagID]].c_str());
sendToReportWindow(L"\n");
}
}
}
}
delete[] conversation; delete[] lineType;
}

Related

looking for explanation for a part of a code

I have this function a student represented by id going to add a course in a specific semester. this code is correct but i don't understand the section when he did
for (size_t i = 0; i < (*iteratorVectorP).size(); i++) ...
void add_course(map<int, map<int, vector<course *> * > > &DB, int
semester, int id, course c)
{
auto iterator = DB.find(id); //find id as key, set map to value
vector<course*> *pointer = new vector<course*>;
if (iterator != DB.end())
{
auto iterator1 = ((*iterator).second).find(semester); //find
semester as key, set vector to value
if (iterator1 == (*iterator).second.end()) //if semester does not exist
{
pointer->push_back(new course(c));
(iterator->second)[semester] = pointer;
}
else //if semester exist
{
auto iteratorVectorP = (iterator->second)[semester];
// i do not understand what his doing here
for (size_t i = 0; i < (*iteratorVectorP).size(); i++)
{
if (c == *(*iteratorVectorP)[i])
{
return; //exit when class exist
}
else
{
(*iteratorVectorP).push_back(new course(c));
return;
}
}
}
}
}
the defination of iteratorVectorP is vector, so the for loop is iterating the course and try to add it in the vector if non-existed.
It looks like iteratorVectorP is a pointer, so calling (*iteratorVectorP).size() will get the value it is pointing to.

Access fields of a JSON array using RapidJSON in C++

I am new using the RapidJSON library and I want to know how I can access specific elements within an array in JSON format, this is the JSON:
{
"products": [
{
"id_product": 1,
"product_name": "Beer",
"product_price": 120.00
},
{
"id_product": 2,
"product_name": "Pizza",
"product_price": 20.00
}
]
}
I have this part of the code to make:
Document json_value;
json_value.Parse(json_message); //Above Json
if(!json_value.IsObject())
{
//ERROR
}
if(json_value.HasMember("products"))
{
const Value& a = json_value["products"];
if(a.IsArray())
{
for (SizeType i = 0; i < a.Size(); i++)
{
//Here i dont know how to access the elements of the array elements, but i need something like this:
int element_id = 1; //id_product = 1
string element_name = "Beer"; // product_name = "Beer"
float element_price = 120.00; //prodcut_price = 120.00
}
}
}
You can access the elements of the object using operator[]().
for (SizeType i = 0; i < a.Size(); i++)
{
if (a[i].IsObject()) {
int element_id = a[i]["id_product"].GetInt();
string element_name = a[i]["product_name"].GetString();
double element_price = a[i]["product_price"].GetDouble();
}
}
Please note that you might want to add checks for the type and existence of the member if your JSON is not always consistent.
Since for each "product" in products is an object, you can also iterate each key,value pair like this:
const Value& products = json_value["products"];
for (auto& product: products) { // products is type Array
for (auto& prod : product.GetObject()) {
std::cout << prod.name // similar to map->first
// i.e "id_product", "product_name"
<< prod.value // similar to map->second
// i.e 2, "Pizza"
<< std::endl;
}
}
I believe you can just call operator[]() with an unsigned int, if the value is an array. The tutorial appears to confirm this:
const Value& a = document["a"];
assert(a.IsArray());
for (SizeType i = 0; i < a.Size(); i++) // Uses SizeType instead of size_t
printf("a[%d] = %d\n", i, a[i].GetInt());
You can also get iterators using MemberBegin() and MemberEnd().

Get index of a column with the header of column (CListCtrl) mfc c++

Every time i use IsertColumn function it will return an int variable. That variable is a index of a column.
If we have a lot of columns, is there any way to get that index of a column with given name (header text of that column).
Thank you
Per your request, something similar to this should work....
This example derives a CListCtrl to be used within a dialog.
int MyListCtrl::FindColumn(const CString& ColumnText)
{
int index = -1;
CHeaderCtrl* pHeader = GetHeaderCtrl();
if (pHeader)
{
int NumberOfColumns = pHeader->GetItemCount();
for (int i = 0; i < NumberOfColumns; ++i)
{
HDITEM Item;
TCHAR buffer[256] = { 0 };
Item.mask = HDI_TEXT;
Item.pszText = buffer;
Item.cchTextMax = 256;
pHeader->GetItem(i, &Item);
if (Item.pszText == ColumnText)
{
index = i;
break;
}
}
}
return index;
}
To call the function:
int index = m_llistctrl.FindColumn(_T("Value"));
Where "Value" is the text of an actual column in the header.
CListCtrl::GetHeaderCtrl::GetItem(int iPos, HDITEM* pHeaderItem);
HDITEM::pszText is what you want - if I got your question correctly...

Inserting values of an map with vectors

I have the following map:
std::map<u_long, std::vector<CChatContainer*> >m_Container;
class CChatContainer
{
public:
CChatContainer()
{
m_uStartPos = 0;
m_uEndPos = 0;
m_dwColor = NULL;
m_pItemElem = NULL;
}
~CChatContainer(){};
u_long m_uStartPos;
u_long m_uEndPos;
DWORD m_dwColor;
void* m_pItemElem;
};
how do I insert values in it, the vector part seems very complex to me
Example:
u_long j = 2; // get index in the map - where to insert
std::vector<CChatContainer*> conts; // create container to insert
for( int i = 0; i < N; i++ ) { // fill the container
CChatContainer* new_cont = new CChatContainer;
cont.push_back(new_cont);
}
m_Container[j] = conts; // insert

How do you add a repeated field using Google's Protocol Buffer in C++?

I have the below protocol buffer. Note that StockStatic is a repeated field.
message ServiceResponse
{
enum Type
{
REQUEST_FAILED = 1;
STOCK_STATIC_SNAPSHOT = 2;
}
message StockStaticSnapshot
{
repeated StockStatic stock_static = 1;
}
required Type type = 1;
optional StockStaticSnapshot stock_static_snapshot = 2;
}
message StockStatic
{
optional string sector = 1;
optional string subsector = 2;
}
I am filling out the StockStatic fields while iterating through a vector.
ServiceResponse.set_type(ServiceResponse_Type_STOCK_STATIC_SNAPSHOT);
ServiceResponse_StockStaticSnapshot stockStaticSnapshot;
for (vector<stockStaticInfo>::iterator it = m_staticStocks.begin(); it!= m_staticStocks.end(); ++it)
{
StockStatic* pStockStaticEntity = stockStaticSnapshot.add_stock_static();
SetStockStaticProtoFields(*it, pStockStaticEntity); // sets sector and subsector field to pStockStaticEntity by reading the fields using (*it)
}
But the above code is right only if StockStatic was an optional field and not a repeated field. My questions is what line of code am i missing to make it a repeated field?
No, you're doing the right thing.
Here's a snippet of my protocol buffer (details omitted for brevity):
message DemandSummary
{
required uint32 solutionIndex = 1;
required uint32 demandID = 2;
}
message ComputeResponse
{
repeated DemandSummary solutionInfo = 3;
}
...and the C++ to fill up ComputeResponse::solutionInfo:
ComputeResponse response;
for ( int i = 0; i < demList.size(); ++i ) {
DemandSummary* summary = response.add_solutioninfo();
summary->set_solutionindex(solutionID);
summary->set_demandid(demList[i].toUInt());
}
response.solutionInfo now contains demList.size() elements.
Here the c++ sample code but may not efficient:
message MyArray
{
repeated uint64 my_data = 1;
}
//Copy
std::array<unsigned long long, 5> test={1,1,2,3,5};
mynamespace::MyArray pbvar;
auto *dst_ptr = keys.my_data();
google::protobuf::RepeatedField<google::protobuf::uint64> field{test.begin(), test.end()};
dst_ptr->CopyFrom(field);
//Output
for (auto it : pbvar.my_data())
std::cout<<it<<" ";
std::cout<<std::endl;
Another way of accomplishing the same thing:
message SearchResponse {
message Result {
required string url = 1;
optional string title = 2;
repeated string snippets = 3;
}
repeated Result result = 1;
}