2016-11-07 2 views
2

Это концептуальный вопрос, поэтому я не предоставляю «рабочий код» по этой причине.Создание связи между двумя векторами в C++

Представьте себе один имеет два зЬй :: вектор различных типов и различного числа лиц, просто к примеру:

vector <int> A; 
vector <string> B; 

Один имеет набор правил, после чего можно связать любые члены с некоторыми (или нет) членов B.

Есть ли способ «сохранить» это соединение?

Я думал, что один из способов сделать это - иметь vector <map <int, vector <string> > > или vector <map <int, vector <string*> > >, но это решение кажется мне ненадежным (если A содержит два одинаковых номера, например), и я предполагаю, что там есть гораздо более элегантные решения ,

+0

Как вы описали его, 'std :: map >' представляется более подходящим. –

+0

@ πάνταῥεῖ, это вопрос того, что действительно нужно - быстро получить a-> b или b-> a. И, следовательно, возможно, более сложное решение будет очень полезно. Кроме того, ничто не мешает нам иметь те же объекты в B :) – greyxray

+0

Предоставить дополнительную информацию - если в A (B) есть дубликаты, как они будут отображаться на B (A)? Или на самом деле означает, что вы связываете векторные позиции/индексы? Это вопрос о функциях (математических), а затем код. – kabanus

ответ

2

Вы могли бы реализовать некоторые базы данных методы: индексы. Поместите свои данные в один vector, затем создайте std::map для каждого способа индексирования ваших данных или их передачи.

Вместо 2 векторов, сделать один вектор структур:

struct Datum 
{ 
    int value; 
    string text; 
}; 

// The database 
std::vector<Datum> database; 

// An index table by integer 
std::map<int, // Key 
     unsigned int vector_index> index_by_value; 

// An index table, by text 
std::map<std::string, // Key 
     unsigned int index_into_vector> index_by text; 

Таблица индексов дает вам быстрый способ найти вещи в базе данных, без необходимости сортировки базы данных.

2

A std::multiset из std::pair ы могли бы сопоставить несколько int* с до нуля или более std::string* сек:

std::multiset < std::pair<int*, std::vector<std::string*>>> map_A_to_B; 

Пример:

#include <set> 
#include <vector> 
#include <string> 
#include <utility> 
#include <iostream> 

int main() 
{ 
    std::vector<int> A{3,3,1,5}; 
    std::vector<std::string> B{"three a", "three b", "one", "five", "unknown"}; 
    std::multiset < std::pair<int*, std::vector<std::string*>>> map_A_to_B{ 
     {&A[0],{&B[0],&B[1]}}, 
     {&A[1],{&B[0],&B[1],&B[4]}}, 
     {&A[2],{&B[2]}}, 
     {&A[3],{&B[3]}}, 
    }; 

    for(auto e : map_A_to_B) { 
     for(auto s : e.second) { 
      std::cout << *e.first << " linked to " << *s << '\n'; 
     } 
     std::cout << "------------------------------\n"; 
    } 
} 

производит:

3 linked to three a 
3 linked to three b 
------------------------------ 
3 linked to three a 
3 linked to three b 
3 linked to unknown 
------------------------------ 
1 linked to one 
------------------------------ 
5 linked to five 
------------------------------ 
1

Based на ваш комментарий, кажется, что вы ant - фактическое отображение (как в математике, из множества A в множество B), которое является общим (не взаимно-однозначным или на). Сначала вы должны концептуально понять, чего хотите. Во-первых, вам требуется сопоставление между классом A (например, int в вашем примере) с B (строка). Давайте шаблон это:

template <class From, class To> 
bool isMapped(From A,To B) { 
    return (//Code representing mapping,say check if A=int->char is in B=string) 
} 

Теперь отображение значения From к To вектора (в математике терминах) диапазон в «To», который достижим (isMapped) образуют следующее значение:

template<class From, class To> 
List<To>& getRange(From value, To range) { 
    List<To> result(); 
    for (const auto& toValue : range) { 
     if(isMapped(value,toValue) 
      result.push_back(toValue); 
    return result; 

Это значение будет возвращено в значение From в вектор To с дубликатами, если они отображаются более одного раза в диапазоне. Другой вариант (возможно, лучше) состоял бы в том, чтобы перебирать индексы вместо значений в диапазоне и возвращать булевский вектор длины range с true в индексы, в которых отображен From.

Аналогичным образом вам необходимо определить противоположное отображение. Вероятно, вы не могли бы сделать это полностью общим, и, возможно, даже шаблоны не будут соответствовать этому просто - вам нужно будет дать больше информации.

Таким образом, отображение из A в B будет вектором длины вектора A (домена) векторов длины B (домена) с True/False в соответствующих индексах.

Есть, конечно, больше возможностей.

1

Вы можете использовать Boost для реализации bidirectional map - это позволит вам использовать любое из значений в качестве ключа. Here is an example of how to use it.Но, короче говоря: (только использование, без определений)

struct from {}; // tag for boost 

typedef bidirectional_map<int, std::string>::type bi_map; 

bi_map values; 
values.insert(bi_map::value_type(123, "{")); 

// ... 
// ... 

bi_map::iterator it = values.get<from>().find(123); 
if (it != values.end()) { 
    cout << "Char #123 is " << it->second << endl; 
    // and in the opposite case, where "it" is the result of: 
    // values.get<to>().find("{") 
    // it->second would be 123, so you have access to both items 
} 
Смежные вопросы