How Can I Swap Map Elements without Moving? - c++

If I have two map<string, int>s how can I swap an element from each map?
For example:
map<string, int> ps{ { "triangle", 0 }, { "cross", 1 }, { "square", 2 }, { "circle", 3 } };
map<string, int> xbox{ { "y", 0 }, { "a", 1 }, { "b", 2 }, { "x", 3 } };
swap(move(ps["cross"]), move(xbox["x"]));
The swap statement is clearly wrong, but that explains what I want to do. After the swap statement I'd like ps to contain:
{ "triangle", 0 }
{ "x", 3 }
{ "square", 2 }
{ "circle", 3 }
And xbox to contain:
{ "y", 0 }
{ "a", 1 }
{ "b", 2 }
{ "cross", 1 }
I expect there is a good way to do this with C++11's move syntax, but if possible I'd like an answer that also describes how to accomplish this on C++03.

map is implemented as an ordered tree.
You cannot simply replace a key with a new key as it might have to be placed on a different location in the tree. Consequently, you cannot swap.
Delete an re-insert the k-v pairs manually.
(As a sidenote: you haven't even told us what happens with the values...)

Related

mapreduce in couchDB and getting the MAX result after mapreduce

I am a beginner to couchDB.
I have data as below:
one:[{
"name":abc,
"value":1
},
{
"name":efg,
"value":1
},
{
"name":abc,
"value":1
},
I would like to get the count of similar keys and get the maximum.
e.g. in my case "abc" is twice. so the maximum(reduce function) should return
result: {"name":abc,value:2}
Did you try this design document:
{
"_id":"_design/company",
"views":
{
"abc_customers": {
"map": "function(doc) { if (doc.name == 'abc') emit(doc.name,doc.value) }",
"reduce" : "_count"
},
"efg_customers": {
"map": "function(doc) { if (doc.name == 'efg') emit(doc.name,doc.value) }",
"reduce" : "_count"
}
}
}
See this one for a comparison of _count and _sum. Possibly you need _count.
By the above CouchDB design document, you will get count for each doc.name of abc, efg, ... and then you can do a search for max/min of counts.

Using Linq to order lists within a list

I have a list of items (actually an IEnumerable). Each item has a list of values. For example:
Item1.Value[0] = "Health & Safety"
Item1.Value[1] = "Economic"
Item1.Value[2] = "Environment"
Item2.Value[0] = "Reputation"
Item2.Value[1] = "Environment"
Item2.Value[2] = "Regulatory"
...
How can I order the list of values using linq? I know I can order the list of items using something like:
Items.Orderby(x => x.something)
...but how do I get to the list of values in each item?
You can try this
Items.ForEach(i=> x.something = x.something.OrderBy(o=> o.field));
EDIT: Based off OP's comment, Value is a Dictionary<string, object>. You cannot sort a Dictionary as they are unordered by design.
Consider using a SortedDictionary<TKey, TValue>, and implement an IComparer<TKey> to fit your sorting needs:
Example:
Dictionary<string, object> values = new Dictionary<string, object>
{
{ "b", 1 }, { "a", 2 }, { "c", 3 }
};
// { { "a", 2 }, { "b", 1 }, { "c", 3 } }
SortedDictionary<string, object> keyAscending =
new SortedDictionary<string, object>(values);
public class ReverseStringComparer : IComparer<string>
{
int IComparer<string>.Compare(string x, string y)
{
return y.CompareTo(x);
}
}
// { { "c", 3 }, { "b", 1 }, { "a", 2 } }
SortedDictionary<string, object> keyDescending =
new SortedDictionary<string, object>(values, new ReverseStringComparer());

replacing fields from json formating using easier methodology in Qt 5.7 using QVariantMaps

I have 3 variantMaps created from JSON and I would like to substitute
for example all 3 things from 3d with 2nd and than second to first to the properties.
QVariantMap wholeMapToChange; //1.
QVariantMap propertiesMapToChange; //2.
QVariantMap cmdMap; //3.
1st contain this JSON data but in map:
{
properties {
"A": true,
"B": true,
"fieldName": "ewfqfqewf",
"C": false,
"fieldPassword": "451541611",
"isBtnSignOnClicked": true
},
type: "xyz"
}
2nd contain this JSON data but in map:
{
"A": true,
"B": true,
"fieldName": "ewfqfqewf",
"C": false,
"fieldPassword": "451541611",
"isBtnSignOnClicked": true
}
3d contain this JSON data but in map:
{
"fieldName": "nick",
"fieldPassword": "0000",
"isBtnSignOnClicked": true
}
What I see as a possibility for substituing 3 with 2 is to create cycle
for (QVariantMap::const_iterator it = propertiesMapToChange.begin(); it != propertiesMapToChange.end(); ++it){
for (QVariantMap::const_iterator itt = cmdMap.begin(); itt != cmdMap.end(); ++itt){
///here would be the comparig...
}
}
But I dont think this is good solution... I would like to ask you for advice or opinion, whether its correct, or there exist better way to do that.
Thx
It is the right solution if the maps aren't too big, since the cost is N*M. But it is a premature pessimization. You should implement the loop to have N+M cost: after all, the maps are sorted, so you only need to iterate each map once.
A complete example:
// https://github.com/KubaO/stackoverflown/tree/master/questions/json-map-iter-39979440
#include <QtCore>
QVariantMap replaceMap(QVariantMap dst, const QVariantMap & src) {
auto dit = dst.begin();
auto sit = src.begin();
while (dit != dst.end() && sit != src.end()) {
if (sit.key() < dit.key()) {
++ sit;
continue;
}
if (dit.key() < sit.key()) {
++ dit;
continue;
}
Q_ASSERT(sit.key() == dit.key());
dit.value() = sit.value();
++ sit;
++ dit;
}
return dst;
}
int main() {
auto json1 = QJsonDocument::fromJson({R"ZZ({
"properties":{
"A":true,
"B":true,
"fieldName":"ewfqfqewf",
"C":false,
"fieldPassword":"451541611",
"isBtnSignOnClicked":true
},
"type":"xyz"
})ZZ"}).toVariant().value<QVariantMap>();
auto json2 = QJsonDocument::fromJson({R"ZZ({
"A":true,
"B":true,
"fieldName":"ewfqfqewf",
"C":false,
"fieldPassword":"451541611",
"isBtnSignOnClicked":true
})ZZ"}).toVariant().value<QVariantMap>();
auto json3 = QJsonDocument::fromJson(
{R"ZZ({
"fieldName":"nick",
"fieldPassword":"0000",
"isBtnSignOnClicked":true
})ZZ"}).toVariant().value<QVariantMap>();
json2 = replaceMap(json2, json3);
auto props = replaceMap(json1["properties"].value<QVariantMap>(), json2);
json1["properties"] = props;
qDebug() << QJsonDocument::fromVariant(json1).toJson().constData();
}
Output:
{
"properties": {
"A": true,
"B": true,
"C": false,
"fieldName": "nick",
"fieldPassword": "0000",
"isBtnSignOnClicked": true
},
"type": "xyz"
}

Initialize two dimensional array with different columns sizes in c++ [duplicate]

This question already has answers here:
Do jagged arrays exist in C/C++?
(12 answers)
Closed 8 years ago.
Is there a way to initialize two dimensional array with different size of columns in c++?
I try to make console card game.
I have done something like this while ago.
static string const group[7][];
string const Cards::group = {
{ "AA", "KK", "AKs" },
{ "QQ", "JJ", "AK", "AJs", "KQs", "AQs" },
{ "TT", "AQ", "ATs", "KJs", "QJs", "JTs" },
{ "99", "88", "AJ", "AT", "KQ", "KTs", "QTs", "J9s" , "T9s" , "98s" },
{ "77", "66", "A9s", "A5s", "A4s", "A3s", "A2s", "K9s", "KJ", "KT", "QJ", "QT", "Q9s", "JT", "QJ", "T8s", "97s", "87s", "76s", "65s"},
{ "55", "44", "33", "22", "K9", "J9", "86s"},
{ "T9", "98", "85s"}
};
It doesn't work.
It would be great if an array would be additionally static and constant but it isn't necessary. The most important thing is to make code works.
I would be grateful for any kind of help.
Arrays in C++ are not truly dynamic; they cannot be extended nor reduced in size. Moreover, the dimensions of static arrays have to be known at their declaration. Dynamically-allocated arrays can be used by declaring group as a string** and later initializing it with the appropriately-sized memory. You can also use a 2-dimensional vector which is fundamentally equivalent but preferred because it is cleaner because we can leverage its memory management:
static std::vector<std::vector<std::string>> const group;
std::vector<std::vector<std::string>> Cards::group = {
{ "AA", "KK", "AKs" },
{ "QQ", "JJ", "AK", "AJs", "KQs", "AQs" },
{ "TT", "AQ", "ATs", "KJs", "QJs", "JTs" },
{ "99", "88", "AJ", "AT", "KQ", "KTs", "QTs", "J9s" , "T9s" , "98s" },
{ "77", "66", "A9s", "A5s", "A4s", "A3s", "A2s", "K9s", "KJ", "KT", "QJ", "QT", "Q9s", "JT", "QJ", "T8s", "97s", "87s", "76s", "65s"},
{ "55", "44", "33", "22", "K9", "J9", "86s"},
{ "T9", "98", "85s"}
};
You can't use:
string group[7][] =
However, you can use:
std::vector<std::string> group[] =
Here's a working program.
#include <iostream>
#include <string>
#include <vector>
std::vector<std::string> group[] =
{
{ "AA", "KK", "AKs" },
{ "QQ", "JJ", "AK", "AJs", "KQs", "AQs" },
{ "TT", "AQ", "ATs", "KJs", "QJs", "JTs" },
{ "99", "88", "AJ", "AT", "KQ", "KTs", "QTs", "J9s" , "T9s" , "98s" },
{ "77", "66", "A9s", "A5s", "A4s", "A3s", "A2s", "K9s", "KJ", "KT", "QJ", "QT", "Q9s", "JT", "QJ", "T8s", "97s", "87s", "76s", "65s"},
{ "55", "44", "33", "22", "K9", "J9", "86s"},
{ "T9", "98", "85s"}
};
int main()
{
for ( auto it1 : group )
{
for ( auto it2 : it1 )
{
std::cout << it2 << " ";
}
std::cout << std::endl;
}
}
You cannot do
string group[7][];
Instead, you can only do
string group[][7];
for multidimensional C-style arrays.
If you truly need multidimensional array with different sizes in the last dimension, you can use std::vector> with STL.

How do I declare a multi-dimensional array in C++?

The following is an example of a multi-dimensional array declaration in C#:
var Number = new double[2, 3, 5]
{
{
{ 12.44, 525.38, -6.28, 2448.32, 632.04 },
{-378.05, 48.14, 634.18, 762.48, 83.02 },
{ 64.92, -7.44, 86.74, -534.60, 386.73 }
},
{
{ 48.02, 120.44, 38.62, 526.82, 1704.62 },
{ 56.85, 105.48, 363.31, 172.62, 128.48 },
{ 906.68, 47.12, -166.07, 4444.26, 408.62 }
},
};
I would like to do the same in C++, but do not know how and have not read my C++ book.
How can I accomplish this?
Here is a naive way of doing that without explicitly specifying the bounds:
vector<vector<vector<double>>> v =
{
{
{ 12.44, 525.38, -6.28, 2448.32, 632.04 },
{-378.05, 48.14, 634.18, 762.48, 83.02 },
{ 64.92, -7.44, 86.74, -534.60, 386.73 }
},
{
{ 48.02, 120.44, 38.62, 526.82, 1704.62 },
{ 56.85, 105.48, 363.31, 172.62, 128.48 },
{ 906.68, 47.12, -166.07, 4444.26, 408.62 }
},
};
However, the vector of vectors will allow you to push elements into each dimension freely (they are just independent vectors), so you might end up not having a consistent multi-dimensional vector. In particular, the compiler won't detect any attempt to put more or less elements into one dimension than into another one.
If that is a concern, you might want to check Boost.MultiArray.
You don't need the standard library, or Boost, to define and initialize a fixed size multidimensional array.
double Number[2][3][5] =
{
{
{ 12.44, 525.38, -6.28, 2448.32, 632.04 },
{-378.05, 48.14, 634.18, 762.48, 83.02 },
{ 64.92, -7.44, 86.74, -534.60, 386.73 }
},
{
{ 48.02, 120.44, 38.62, 526.82, 1704.62 },
{ 56.85, 105.48, 363.31, 172.62, 128.48 },
{ 906.68, 47.12, -166.07, 4444.26, 408.62 }
},
};