Хитрая задачка
Производитель, поставщик, срок пользования.
Надо подсчитать сколько различных комбинаций этих трех полей встречается.
Потом, соответсвенно разбить эту таблицу на подтаблицы количеством равным количеству комбинаций. То есть:
Таблица до изменений:
|Производитель|Поставщик|Срок|Номер|
|12 |1 |3 |0
|13 |1 |3 |0
|12 |1 |3 |0
|12 |1 |2 |0
|13 |2 |3 |0
|13 |1 |3 |0
|13 |1 |2 |0
Подсчет:
|Производитель|Поставщик|Срок|Номер|
|12 |1 |3 |0
2 штуки;
|Производитель|Поставщик|Срок|Номер|
|12 |1 |2 |0
1 штука;
|Производитель|Поставщик|Срок|Номер|
|13 |1 |3 |0
2 штуки;
|Производитель|Поставщик|Срок|Номер|
|13 |2 |3 |0
1 штука;
|Производитель|Поставщик|Срок|Номер|
|13 |1 |2 |0
1 штука;
Измененная таблица:
|Производитель|Поставщик|Срок|Номер|
|12 |1 |3 |1
|13 |1 |3 |3
|12 |1 |3 |1
|12 |1 |2 |2
|13 |2 |3 |4
|13 |1 |3 |3
|13 |1 |2 |5
Есть идея решить это все с помощью STL но что-то ума не приложу как. В принципе с помощью std::vector можно попытаться решить.
типа
class MySpec
{
public:
int Vendor;
int Dealer;
int Month;
};
std::vector<MySpec> vMySpec;
но потом вот вопрос как сделать так чтоб
vMySpec.push_back(MySpec);
осуществлял вставку только в том случае если класса с такими членами еще нет в векторе.
Если да то
select a,b,c, count(a) from post group by a,b,c
У тебя это в БД?
Если да то
select a,b,c, count(a) from post group by a,b,c
Эх, еслиб все так просто было, это уже в ClientDataSet.
> std::vector<MySpec> vMySpec;
> но потом вот вопрос как сделать так чтоб
> vMySpec.push_back(MySpec);
> осуществлял вставку только в том случае если
> класса с такими членами еще нет в векторе.
1)
Возможно тебе подойдет unique_copy?
//
// unique.cpp
//
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
int main()
{
//Initialize two vectors
int a1[20] = {4, 5, 5, 9, -1, -1, -1, 3, 7, 5,
5, 5, 6, 7, 7, 7, 4, 2, 1, 1};
vector<int> v(a1+0, a1+20), result;
//Create an insert_iterator for results
insert_iterator<vector<int> > ins(result, result.begin());
//Demonstrate includes
cout << "The vector: " << endl << " ";
copy(v.begin(),v.end(),
ostream_iterator<int,char>(cout," "));
//Find the unique elements
unique_copy(v.begin(), v.end(), ins);
//Display the results
cout << endl << endl
<< "Has the following unique elements:"
<< endl << " ";
copy(result.begin(),result.end(),
ostream_iterator<int,char>(cout," "));
return 0;
}
Program Output
The vector:
4 5 5 9 -1 -1 -1 3 7 5 5 5 6 7 7 7 4 2 1 1
Has the following unique elements:
4 5 9 -1 3 7 5 6 7 4 2 1
2) Есть еще map, который в отличии от multimap не позволяет иметь одинаковые ключи. Т.е. в качестве ключа можно иметь структуру из трех твоих полей, а в качестве value частоту...
3) ...
А у тебя IB
У меня MSSQL2k. Содержимое ClientDataSet формируется на клиенте. Так что кидать его на сервер, а потом обратно выдергивать запросом, при том, что пользователь еще может и не захотеть сохранять это в БД, нет никакого резона.
Так что задачка тут явно для STL только вот я с ним уж шибко давно не работал. ВОт так что и задумался.
2 Berg: Щас посмотрим что нам там std::map предложит на эту тему=)))
2 SEDEGOFF:
2 Berg: Щас посмотрим что нам там std::map предложит на эту тему=)))
Если ничего, то вот еще:
1)
- Заполняешь вектор v значениями;
- Делаешь v.sort(), чтобы одинаковые элементы стали соседними;
- Подсчитываешь число вхождений каждогоэлемента через for_each() & count();
- Делаешь
typename типструктуры::iterator
p = unique(v.begin(), v.end());
- v.erase(p, v.end()); При этом удаляются все соседние одинаковые элементы
2) На крайняк можно самому делать find перед вставкой...
Вот с find сейчас и заморачиваюсь, проблема в том что если find не нашел ни одного такого элемента то он возвращает итератор на последний элемент вектора.=)))
Ну щас я его поборю, а так оператор сравнения дописал, получилось вот что:
class MySpec
{
private:
protected:
public:
int Vendor;
int Dealer;
int Month;
bool operator==(const MySpec&);
};
bool MySpec::operator == (const MySpec& rhs)
{
return (this->Vendor == rhs.Vendor &&
this->Dealer == rhs.Dealer &&
this->Month == rhs.Month);
}
Да кстати откуда толковый талмуд по STL желательно на русском можно утянуть?
2 Berg:
Вот с find сейчас и заморачиваюсь, проблема в том что если find не нашел ни одного такого элемента то он возвращает итератор на последний элемент вектора.=)))
А какая тебе разница? Если не нашел делай push и все...А если нашел, то счетчик++ у элемента с вернувшимся итератором или я чего-то не догоняю?
Да кстати откуда толковый талмуд по STL желательно на русском можно утянуть?
Вот тут немного есть от Страуструпа:
http://lib.ru/CPPHB/cpptut.txt
2 Berg:
Вот с find сейчас и заморачиваюсь, проблема в том что если find не нашел ни одного такого элемента то он возвращает итератор на последний элемент вектора.=)))
А какая тебе разница? Если не нашел делай push и все...А если нашел, то счетчик++ у элемента с вернувшимся итератором или я чего-то не догоняю?
Да кстати откуда толковый талмуд по STL желательно на русском можно утянуть?
Вот тут немного есть от Страуструпа:
http://lib.ru/CPPHB/cpptut.txt
Тут более подробно, но на аглицком:
http://www.cs.rpi.edu/projects/stl/htdocs/stl.html
А какая тебе разница? Если не нашел делай push и все...А если нашел, то счетчик++ у элемента с вернувшимся итератором или я чего-то не догоняю?
Да разница в том, что если вектор не пустой, то find в любом случае вернет итератор, если нет совпадений то она вернет указатель на последний элемент вектора.
В общем решил я эту задачку=)))
Вот примерчик:
Да разница в том, что если вектор не пустой, то find в любом случае вернет итератор, если нет совпадений то она вернет указатель на последний элемент вектора.
В общем решил я эту задачку=)))
Вот примерчик:
Посмотрел твой пример.
Во-первых, чем не подошел std::unique ?
Во-вторых есть несколько придирок:
1. Почему бы не сделать так (File.h):
#define My_StructH
class MySpec
{
public:
int Vendor;
int Dealer;
int Month;
bool operator==(const MySpec& rhs)
{
return (this->Vendor == rhs.Vendor &&
this->Dealer == rhs.Dealer &&
this->Month == rhs.Month);
}
bool operator!=(const MySpec& rhs)
{
return !(this==rhs);
}
};
#endif
2. Не только ненужное сравнение, но и опасный код:
(*vMySpec.end() != tmp)
Посмотри, что возвращает end()
3. Условие в Unit1.cpp можно записать проще и нагляднее:
if(it1 == vMySpec.end())
{
AnsiString S = "Vendor: " + IntToStr(tmp.Vendor) + \
", Dealer: " + IntToStr(tmp.Dealer) + \
", Month: " + IntToStr(tmp.Month);
Memo1->Lines->Add(S);
vMySpec.push_back(tmp);
}
Посмотрел твой пример.
Во-первых, чем не подошел std::unique ?
Дык чтобы знать где искать, надо знать что искать. Ну не знал я об этом std::unique, а доки никакой нету=(. Щас вот заказал Effective STL by Scott Meyers.
Во-вторых есть несколько придирок:
1. Почему бы не сделать так (File.h):
#define My_StructH
class MySpec
{
public:
int Vendor;
int Dealer;
int Month;
bool operator==(const MySpec& rhs)
{
return (this->Vendor == rhs.Vendor &&
this->Dealer == rhs.Dealer &&
this->Month == rhs.Month);
}
bool operator!=(const MySpec& rhs)
{
return !(this==rhs);
}
};
#endif
Так пытался, но чегой-то он у меня ругнулся на подобное написание.
2. Не только ненужное сравнение, но и опасный код:
(*vMySpec.end() != tmp)
Посмотри, что возвращает end()
А чего там не так с end()? Я просто думаю что означает загадочная фраза в хелпе "past-the-end"
3. Условие в Unit1.cpp можно записать проще и нагляднее:
if(it1 == vMySpec.end())
{
AnsiString S = "Vendor: " + IntToStr(tmp.Vendor) + \
", Dealer: " + IntToStr(tmp.Dealer) + \
", Month: " + IntToStr(tmp.Month);
Memo1->Lines->Add(S);
vMySpec.push_back(tmp);
}
А вот это действительно, условие в рабочей программе именно в такое и превратилось, просто изначально стояла задача заставить прогу работать, а потом уже оптимизировать.
А чего там не так с end()? Я просто думаю что означает загадочная фраза в хелпе "past-the-end"
end() возвращает итератор указывающий за последний элемент вектора, т.е. за пределы самого вектора. Т.о. получается, что он указвает в никуда (в контексте данного вектора), т.е. сам указатель невалиден и его разыменовавание опасно.