Какая C ++ лучшая альтернатива dict (zip (values …)) в python?
Я сейчас занимаюсь с преподавателем на языке C ++ в свободное время, наткнулся на кусок кода Python на своей работе и обнаружил, что не знаю лучшего ответа.
Код выглядит следующим образом (я изменил имена переменных и немного обобщил их, но это та же идея):
(dict(zip(wordCollection, [word.strip() for word in currentLine.split(',')][1:-1])))
Я заменил раздетые и разбитые слова на обрезанный токенизированный вектор, используя boost, и это прекрасно работает; однако я потерпел неудачу, пытаясь найти лучший способ перевести комбинацию dict / zip.
Вы действительно не должны пытаться переводить идиомы напрямую с одного языка на другой.
В C ++ вы обычно не пишете функции, которые принимают итераторы и генерируют новые итераторы; вместо этого вы пишете функции, которые принимают итераторы ввода и вывода и копируют из одного в другое. Итак, вы могли бы написать zip
функция, принимающая входной итератор T
входной итератор U
и выходной итератор над pair<T, U>
,
Но тогда вы не собираетесь связывать два вызова таким образом, потому что ваш zip
функция не собирается возвращать что-либо (например, диапазон итераторов), которое можно было бы с пользой передать любому виду dict
функция. Вместо этого вы можете создать dict
аналог unordered_map
), создайте в нем выходной итератор и используйте zip
функция для копирования пар в него.
Что-то вроде этого:
template <I1, I2, O>
void zip(I1 it1, I1 it1end, I2 it2, I2 it2end, O o) {
while ((it1 != it1end) && (it2 != it2end)) {
*o++ = std::make_pair(*it1++, *it2++);
}
}
std::unordered_map<T, U> mapping;
zip(c1.begin(), c1.end(), c2.begin(), c2.end(), std::inserter(mapping, mapping.end()));
Кроме я не думаю, что вы можете использовать inserter
на unordered_map
так или нет, так что вы должны написать map_inserter
функция вместо
Если вы не знаете, типы T
а также U
локально вы можете обернуть все это в шаблон функции, который извлекает типы из типов элементов итераторов, чтобы вы могли auto
Это. (В C ++ 11 вы можете decltype
это без необходимости функции, но выражение будет беспорядок.)
Если у вас есть несколько вариантов использования zip
а также map_inserter
, может быть, стоит написать их. Но в противном случае лучшим решением было бы развернуть его в явный цикл:
auto it1 = c1.begin(), it1end = c1.end(), it2 = c2.begin(), it2end = c2.end();
std::unordered_map<T, U> mapping;
while ((it1 != it1end) && (it2 != it2end)) {
mapping[*it1++] = *it2++;
}
Хорошо, когда у вас есть такие векторы, как:
std::vector<std::string> wordCollection;
std::vector<std::string> splitWords;
тогда вы можете просто повторить:
std::map<std::string, std::string> dict; // or std::unordered_map
std::size_t minSize = std::min(wordCollection.size(), splitWords.size());
for (size_t i = 0; i != minSize; ++i) {
dict.insert(std::make_pair(wordCollection[i], splitWords[i]));
}
ИМО, лучшая альтернатива С ++ для dict
является std::unordered_map
, который является хеш-таблицей, и для zip
, его ranges::view::zip
от D4128 предложение по диапазонам, для которого справочная реализация может быть доступна в github.com/ericniebler/range-v3.
Код C ++ 11:
#include <string>
#include <vector>
#include <unordered_map>
#include <range/v3/view/zip.hpp>
int main() {
using namespace std;
using ranges::view::zip;
int ints[] = {1, 2, 3};
vector<string> strings = {"a", "b"};
unordered_map<int, string> dict(zip(ints, strings));
}
Я надеюсь, что это станет стандартом C ++ в будущем.
dict(zip(labels,values)) ---> dict([("a",1),("b",0)]) ---> dict(a=1,b=0)
dict — это просто хеш-таблица … и это просто создание хеш-таблицы меток и значений, где метки (или ключи) wordCollection
и токенизированная строка является значениями
так что, вероятно, хеш-таблица … хотя, вероятно, потребуется больше одной строки, чтобы сделать это в C ++