#c #unordered-set
#c #неупорядоченный набор
Вопрос:
когда я пытаюсь вставить в эту карту:
std::map<std::unordered_set<int >, std::pair<float, std::pair<float, float >> >
Я получил эту ошибку
ошибка C2784: ‘bool std::operator <(const std::_Tree<_Traits> amp;,const std::_Tree<_Traits> amp;)’: не удалось вывести аргумент шаблона для ‘const std::_Tree<_Traits> amp;’ из ‘const std::unordered_set,std::equal_to<_Kty>,std::распределитель<_Kty>>’
Мои данные определяются следующим образом:
struct Trans {
int Item;
float Prob;
float W;
};
bool operator<(const Trans amp;a, const Trans amp;b)
{
return a.Item < b.Item;
}
bool operator==( Trans c, Trans d) { return c.Item == d.Item; }
struct MyHash {
size_t operator()(const Transamp; x) const { return std::hash<int>()(x.Item); }
};
std::vector<std::vector<Trans>> data;
std::map<std::unordered_set<int>, float> S1;
std::map<std::unordered_set<int >, std::pair<float, std::pair<float, float >> > S2;
std::map<std::unordered_set<int >, std::pair<float, std::pair<float, float >> > S3;
Часть, в которой проблема:
do
{
std::unordered_set<Trans, MyHash> KS(data[i].begin(), data[i].begin() k);
std::unordered_set<int > elem;
float esupp = 1;
float Weight = 0;
float Wesupp = 1;
for (auto const amp;iter : KS)
{
elem.insert(iter.Item);
esupp *= iter.Prob;
Weight = iter.W;
}
Weight = Weight / k;
/*
some code, and until here I didn't get any problem
*/
**// This the area that has the problem**
S1[elem] = std::move(S1[elem] esupp);
Wesupp = Weight * S1[elem];
S2[elem].first = std::move(S2[elem].first esupp);
S2[elem].second = std::make_pair(elem, Wesupp);
} while (next_combination(data[i].begin(), data[i].begin() k, data[i].end()));
Комментарии:
1. Какая фактическая строка содержит ошибку?
2. Помимо всего прочего, эта строка выглядит неправильно:
S2[elem].second = std::make_pair(elem, Wesupp);
3. Я бы серьезно пересмотрел дизайн структуры данных…
unordered_set
как ключи?std::pair<float, std::pair<float, float>>
? (по крайней мере, используйтеstd::tuple
илиstd::array<float, 3>
)4. @ben каждую строку из ` S1 [elem] = std::move(S1[elem] esupp)` в ` S2[elem].second = std::make_pair(elem, Wesupp);` вызывает ошибку
5.@marco-a в контейнер
S2
я хотел бы вставитьunordered_set
elem
с его тремя значениями с плавающей запятой. каждый раунд в циклеelem
имеетunordered_set
, если он похож на предыдущий, я обновлю их три значения с плавающей запятой, в противном случае я вставлю newunordered_set
с его тремя значениями с плавающей запятой.
Ответ №1:
A std::map
ожидает, что его ключ реализует оператор <
, если не указан компаратор.
Ваш тип ключа std::unordered_set
не реализует «меньше».
Как упоминает @T.C., вы могли бы использовать std::set
вместо std::unordered_set
.
Комментарии:
1. спасибо, но если я заменю на
std::map
,std::unordered_map
я получу другую ошибку,error C2338: The C Standard doesn't provide a hash for this type.
2. @Sandy Тогда я удалю это предложение. Причина вашей ошибки остается той же. C этого не поддерживает.
3.
std::set
действительноoperator <()
определен стандартом.4. Спасибо вам всем, мне нужно использовать
std::unordered_set
неstd::set
потому, что я использовал хеш-функцию для проверкиKS
наличия супернабора любого из предыдущего набора, который хранится вS2', I have file of 100k lines, each line has different size, and I used
next_combination`для генерацииKS
, и я использовал хеширование для части сравнений, чтобы сократить время вместо использованияSTL includes()
5. @Sandy Ты действительно измерял скорость с
std::set
помощью /std::includes
? Когда речь идет о производительности, всегда измеряйте.
Ответ №2:
Ваша текущая ошибка, как указал Дрю Дорманн, вызвана std::unordered_set
отсутствием an operator <
.
std::set
однако он перегружен operator <
, поэтому вы можете его использовать.
Однако проблема с вашим кодом глубже, чем это. Например:
S1[elem] = std::move(S1[elem] esupp);
Вы присваиваете float
. Нет абсолютно никакого смысла в использовании std::move
, тем более, S1[elem] esupp
что это уже rvalue . Обычный способ написания этой строки будет S1[elem] = esupp;
S2[elem].first = std::move(S2[elem].first esupp);
Та же проблема.
S2[elem].second = std::make_pair(elem, Wesupp);
LHS присваивания равно a std::pair<float, float>
; RHS создает a std::pair<std::unordered_set<int>, float>
.
И, как я упоминал в комментариях, std::pair<float, std::pair<float, float>>
это просто плохой дизайн. Это должна быть, по крайней мере std::tuple
, или даже лучше std::array<float, 3>
, или даже лучше простая структура, которая проясняет, что на самом деле означает каждый из трех поплавков.
Кроме того, использование a set<int>
(неупорядоченного или нет) в качестве ключа в map — довольно странный дизайн. Вы хотите просто поддерживать список set<int>
-3x float
пар, которые вы можете перебирать, или вы действительно хотите иметь возможность эффективно индексировать с помощью a set<int>
? Если вам не нужна эффективная индексация, просто используйте вектор пар, а не карту.
Комментарии:
1. Английский не мой родной язык, поэтому я использовал пример для описания S2, хотелось бы, чтобы у вас было время взглянуть на него. im67.gulfup.com/REB8Fj.png