I have made a form that collects data which is then sent to a database.
Database has 2 tables, one is main and second one is in relation 1-to-many with it.
To make things clear, I will name them: main table is Table1, and child table is ElectricEnergy.
In table ElectricEnergy is stored energy consumption through months and year, so the table has following schema:
ElectricEnergy< #ElectricEnergy_pk, $Table1_pk, January,February, ...,December, Year>
In the form, user can enter data for a specific year. I will try to illustrate this bellow:
Year: 2012
January : 20.5 kW/h
February: 250.32 kW/h
and so on.
Filled table looks like this:
YEAR | January | February | ... | December | Table1_pk | ElectricEnergy_pk |
2012 | 20.5 | 250.32 | ... | 300.45 | 1 | 1 |
2013 | 10.5 | 50.32 | ... | 300 | 1 | 2 |
2012 | 50.5 | 150.32 | ... | 400.45 | 2 | 3 |
Since the number of years for which consumption can be stored is unknown, I have decided to use vector to store them.
Since vectors can’t contain arrays, and I need an array of 13 ( 12 months + year ), I have decided to store the form data into a vector.
Since data has decimals in it, vector type is double.
A small clarification:
vector<double> DataForSingleYear;
vector< vector<double> > CollectionOfYears.
I can successfully push data into vector DataForSingleYear, and I can successfully push all those years into vector CollectionOfYears.
The problem is that user can enter same year into edit box many times, add different values for monthly consumption, which would create duplicate values.
It would look something like this:
YEAR | January | February | ... | December | Table1_pk | ElectricEnergy_pk |
2012 | 20.5 | 250.32 | ... | 300.45 | 1 | 1 |
2012 | 2.5 | 50.32 | ... | 300 | 1 | 2(duplicate!) |
2013 | 10.5 | 50.32 | ... | 300 | 1 | 3 |
2012 | 50.5 | 150.32 | ... | 400.45 | 2 | 4 |
My question is:
What is the best solution to check if that value is in the vector ?
I know that question is “broad” one, but I could use at least an idea just to get me started.
NOTE:
Year is at the end of the vector, so its iterator position is 12.
The order of the data that will be inserted into database is NOT important, there are no sorting requirements whatsoever.
By browsing through SO archive, I have found suggestions for the usage of std::set, but its documentation says that elements can’t be modified when inserted, and that is unacceptable option for me.
On the other hand, std::find looks interesting.
( THIS PART WAS REMOVED WHEN I EDITED THE QUESTION:
, but does not handle last element, and year is at the end of the
vector. That can change, and I am willing to do that small adjustment if std::find can help me.
)
The only thing that crossed my mind was to loop through vectors, and see if the value already exists, but I don’t think it is the best solution:
wchar_t temp[50];
GetDlgItemText( hwnd, IDC_EDIT1, temp, 50 ); // get the year
double year = _wtof( temp ); // convert it to double,
// so I can push it to the end of the vector
bool exists = false; // indicates if the year is already in the vector
for( vector< vector <double> >::size_type i = 0;
i < CollectionOfYears.size(); i++ )
if( CollectionOfYears[ i ] [ ( vector<double>::size_type ) 12 ] == year )
{
exists = true;
break;
}
if( !exists)
// store main vector in the database
else
MessageBox( ... , L”Error”, ... );
I work on Windows XP, in MS Visual Studio, using C++ and pure Win32.
If additional code is needed, ask, I will post it.
Thank you.
Using find_if and lambda filter:
auto match = std::find_if(CollectionOfYears.begin(), CollectionOfYears.end(),
[&year](v){ return year == v.last(); })
if (match == CollectionOfYears.end()){ //no value previously
}
This still iterates the whole array. If you need more efficient search you should keep the array sorted and use binary search or std::set.
Note that vector::end() returns iterator to the element after the last element. This is why std::find ignores the last value (because it is already out of bounds!).
Related
I have an import query (table a) and an imported Excel file (table b) with records I am trying to match it up with.
I am looking for a method to replicate this type of SQL in M:
SELECT a.loc_id, a.other_data, b.stk
FROM a INNER JOIN b on a.loc_id BETWEEN b.from_loc AND b.to_loc
Table A
| loc_id | other data |
-------------------------
| 34A032B1 | ... |
| 34A3Z011 | ... |
| 3DD23A41 | ... |
Table B
| stk | from_loc | to_loc |
--------------------------------
| STKA01 | 34A01 | 34A30ZZZ |
| STKA02 | 34A31 | 34A50ZZZ |
| ... | ... | ... |
Goal
| loc_id | other data | stk |
----------------------------------
| 34A032B1 | ... | STKA01 |
| 34A3Z011 | ... | STKA02 |
| 3DD23A41 | ... | STKD01 |
All of the other queries I can find along these lines use numbers, dates, or times in the BETWEEN clause, and seem to work by exploding the (from, to) range into all possible values and then filtering out the extra rows. However I need to use string comparisons, and exploding those into all possible values would be unfeasable.
Between all the various solutions I could find, the closest I've come is to add a custom column on table a:
Table.SelectRows(
table_b,
(a) => Value.Compare([loc_id], table_b[from_loc]) = 1
and Value.Compare([loc_id], table_b[to_loc]) = -1
)
This does return all the columns from table_b, however, when expanding the column, the values are all null.
This is not very specific "After 34A01 could be any string..." in trying to figure out how your series progresses.
But maybe you can just test for how a value "sorts" using the native sorting function in PQ.
add custom column with table.Select Rows:
= try Table.SelectRows(TableB, (t)=> t[from_loc]<=[loc_id] and t[to_loc] >= [loc_id])[stk]{0} otherwise null
To reproduce with your examples:
let
TableB=Table.FromColumns(
{{"STKA01","STKA02"},
{"34A01","34A31"},
{"34A30ZZZ","34A50ZZZ"}},
type table[stk=text,from_loc=text,to_loc=text]),
TableA=Table.FromColumns(
{{"34A032B1","34A3Z011","3DD23A41"},
{"...","...","..."}},
type table[loc_id=text, other data=text]),
//determine where it sorts and return the stk
#"Added Custom" = Table.AddColumn(#"TableA", "stk", each
try Table.SelectRows(TableB, (t)=> t[from_loc]<=[loc_id] and t[to_loc] >= [loc_id])[stk]{0} otherwise null)
in
#"Added Custom"
Note: if the above algorithm is too slow, there may be faster methods of obtaining these results
I have a table with numeric values and blank records. I'm trying to calculate a number of rows that are not blank and bigger than 20.
+--------+
| VALUES |
+--------+
| 2 |
| 0 |
| 13 |
| 40 |
| |
| 1 |
| 200 |
| 4 |
| 135 |
| |
| 35 |
+--------+
I've tried different options but constantly get the next error: "Cannot convert value '' of type Text to type Number". I understand that blank cells are treated as text and thus my filter (>20) doesn't work. Converting blanks to "0" is not an option as I need to use the same values later to calculate AVG and Median.
CALCULATE(
COUNTROWS(Table3),
VALUE(Table3[VALUES]) > 20
)
OR getting "10" as a result:
=CALCULATE(
COUNTROWS(ALLNOBLANKROW(Table3[VALUES])),
VALUE(Table3[VALUES]) > 20
)
The final result in the example table should be: 4
Would be grateful for any help!
First, the VALUE function expects a string. It converts strings like "123"into the integer 123, so let's not use that.
The easiest approach is with an iterator function like COUNTX.
CountNonBlank = COUNTX(Table3, IF(Table3[Values] > 20, 1, BLANK()))
Note that we don't need a separate case for BLANK() (null) here since BLANK() > 20 evaluates as False.
There are tons of other ways to do this. Another iterator solution would be:
CountNonBlank = COUNTROWS(FILTER(Table3, Table3[Values] > 20))
You can use the same FILTER inside of a CALCULATE, but that's a bit less elegant.
CountNonBlank = CALCULATE(COUNT(Table3[Values]), FILTER(Table3, Table3[Values] > 20))
Edit
I don't recommend the CALCULATE version. If you have more columns with more conditions, just add them to your FILTER. E.g.
CountNonBlank =
COUNTROWS(
FILTER(Table3,
Table3[Values] > 20
&& Table3[Text] = "xyz"
&& Table3[Number] <> 0
&& Table3[Date] <= DATE(2018, 12, 31)
)
)
You can also do OR logic with || instead of the && for AND.
I asked the same question on stackexchange db admin, that seems to be the proper place for the question, but the problem is no one even view the question. So I post the same question here again:
I am working on Mysql table insertion. The table creation statement is like:
CREATE TABLE files_table (fid INT NOT NULL AUTO_INCREMENT, idx TINYBLOB, head TINYBLOB, size BLOB, PRIMARY KEY(fid));
I could insert record manually
mysql> select * from files_table order by fid asc;
+-----+------+------+------------+
| fid | idx | head | size |
+-----+------+------+------------+
| 1 | 1 | 1 | 1 |
+-----+------+------+------------+
But when I use the connector to add the next value by using c++ connector:
class StreamBufferData : public std::streambuf
{
public:
StreamBufferData(const char *in_data, size_t in_size)
{
setg(in_data, in_data, in_data + in_size);
}
};
enum{QUERY_SIZE=256;}
char ins[QUERY_SIZE];
strcpy(ins, "INSERT INTO files_table (idx, head, size) VALUES (?,?,?)");
try
{
std::unique_ptr<sql::PreparedStatement> statement(ptr_connection->prepareStatement(ins));
char test_data[2] = "0";
StreamBufferData buffer0(test_data, 2);
std::istream test_s0(&buffer0);
statement->setBlob(1, &test_s0);
strcpy(test_data, "1");
StreamBufferData buffer1(test_data, 2);
std::istream test_s1(&buffer1);
statement->setBlob(2, &test_s1);
strcpy(test_data, "2");
StreamBufferData buffer2(test_data, 2);
std::istream test_s2(&buffer2);
statement->setBlob(3, &test_s2);
statement->executeUpdate();
}
catch(sql::SQLException &e)
{
std::cout << e.what() << ‘\n’;
return;
}
The result is :
+-----+------+------+------------+
| fid | idx | head | size |
+-----+------+------+------------+
| 1 | 1 | 1 | 1 |
| 2 | 2 | 2 | 2 |
+-----+------+------+------------+
Only the last value is correctly inserted into the table. My question is: what is the proper way to user msql::PreparedStatement::setBlob() to set multiple blobs in a query?
[environment]
Ubuntu 16.04.2
MySQL 5.7
MySQL connector version: 7.1.1.7
boost 1.58.0
g++ 5.4.0
Thanks for your help
Rong
The different std::istream objects point to the same buffer which allocated by test_data. I thought the istream object will copy the value in the char array. The fact is, it is not.
It also worths to point out that if the std::istream object is destroyed before the statement->executeUpdate() executed. The last stream object will be filled into the first column of the table, which might be an undefined behavior on my machine (Ubuntu 16.04.2 LTS). It looks like:
+-----+------+------+------------+
| fid | idx | head | size |
+-----+------+------+------------+
| 1 | 1 | 1 | 1 |
| 2 | 2 | | |
+-----+------+------+------------+
So, if the table has strange results like the previous table, check the code to make sure the std::stream, the StreamBufferData and the pointer pointing to the buffer are still valid until statement->executeUpdate() executed.
I need to write a function that takes as arguments an integer, which represents a row in a truth table, and a boolean array, where it stores the values for that row of the truth table.
Here is an example truth table
Row| A | B | C |
1 | T | T | T |
2 | T | T | F |
3 | T | F | T |
4 | T | F | F |
5 | F | T | T |
6 | F | T | F |
7 | F | F | T |
8 | F | F | F |
Please note that a given truth table could have more or fewer rows than this table, since the number of possible variables can change.
A function prototype could look like this
getRow(int rowNum, bool boolArr[]);
If this function was called, for example, as
getRow(3, boolArr[])
It would need to return an array with the following elements
|1|0|1| (or |T|F|T|)
The difficulty for me arises because the number of variables can change, therefore increasing or decreasing the number of rows. For instance, the list of variables could be A, B, C, D, E, and F instead of just A, B, and C.
I think the best solution would to be write a loop that counted up to the row number, and essentially changed the elements of the array like it was counting in binary. So that
1st loop iteration, array elements are 0|0|...|0|1|
2nd loop iteration, array elements are 0|0|...|1|0|
I can't for the life of me figure out how to do this, and can't find a solution elsewhere on the web. Sorry for all the confusion and thanks for the help
Ok now that you rewrote your question to be much clearer. First, getRow needs to take an extra argument: the number of bits. Row 1 with 2 bits produces a different result than row 1 with 64 bits, so we need a way to differentiate that. Second, typically with C++, everything is zero-indxed, so I am going to shift your truth table down one row so that row "0" returns all trues.
The key here is to realize that the row number in binary is already what you want. Take this row (having shifted down the 4 to 3):
3 | T | F | F |
3 in binary is 011, which inverted is {true, false, false} - exactly what you want. We can express that using bitwise-or as the array:
{!(3 | 0x4), !(3 | 0x2), !(3 | 0x1)}
So it's just a matter of writing that as a loop:
void getRow(int rowNum, bool* arr, int nbits)
{
int mask = 1 << (nbits - 1);
for (int i = 0; i < nbits; ++i, mask >>= 1) {
arr[i] = !(rowNum & mask);
}
}
I have similar map:
map<int, map<int, map<int, int> > > myMap;
order-num | id | order-num-of-relation | relation-id
-----------------------------------------------------
0 | 1 | 0 | 2
-----------------------------------------------------
1 | 2 | 0 | 1
-----------------------------------------------------
| | 1 | 3
-----------------------------------------------------
2 | 3 | 0 | 2
-----------------------------------------------------
1(1), 2(2), 3(1)
and i need to sort (change the "order-num") this map by size of the last map (order-num-of-relation | relation-id).
I just need to do this:
order-num | id | order-num-of-relation | relation-id
-----------------------------------------------------
0 | 1 | 0 | 2
-----------------------------------------------------
1 | 3 | 0 | 2
-----------------------------------------------------
2 | 2 | 0 | 1
-----------------------------------------------------
| | 1 | 3
-----------------------------------------------------
1(1), 3(1), 2(2)
can i use the "sort" function and pass here own sorting function (where i can checking size and returing true/false), or do i have to write explicite sorting algorithm?
You don't/can't sort maps. They are automatically sorted by key based on the optional third parameter to the template arguments, which is a function object class used to compare two elements to determine which should come first. (it should return true if the first should come before the second, false otherwise)
So you can use something like this:
struct myCompare
{
bool operator() const (const map<int,int> & lhs, const map<int,int> & rhs)
{
return lhs.size() < rhs.size();
}
};
But since map<int,int> is your value, and not your key, this won't exactly work for you.
What you're looking for has been done in Boost with MultiIndex. Here's a good tutorial from Boost on how you can use it to solve what you're asking of your data collection and their selection of examples.
Of course, using this collection object will probably change how you store the information too. You'll be placing it within a struct. However, if you want to treat your information like a database with a unique order by specification this is the only way I know how that's clean.
The other option is to create your own ordering operator while placing the items in a std::map. Hence:
struct Orders{
int order_num;
int id;
int order_num_relation;
int relation_id;
bool operator<(const Orders& _rhs){
if(order_num < _rhs.order_num) return true;
if(order_num == _rhs.order_num){
if( id < _rhs.id) return true;
if( id == _rhs.id){
//and so on, and so on
Honestly this way is a pain and invites a very easily overlooked logic fault. Using Boost, most of the "tricky" stuff is taken care of for you.