[英]C++: how to compare several vectors, then make a new sorted vector that contains ALL elements of all vectors
更新 :我有一些關於評論者6502的答案的愚蠢問題(如下)。 如果有人可以提供幫助,我將非常感激。
1)我知道數據1和數據2是映射,但是我不知道allkey的作用。 誰能解釋?
2)我知道:data1 [vector1 [i] .name] = vector1 [i] .value; 意味着在感興趣的地圖上為正確的標簽分配一個值...但是我不明白: vector1 [i] .name和vector1 [i] .value 。 “名稱”和“值”不是標簽和值的兩個單獨的向量嗎? 那么他們在vector1上做什么? 這不應該讀為name [i]和value [i]嗎?
感謝大家。
我已經編寫了用於執行計算的代碼。 該代碼使用其他地方的數據。 計算代碼很好,但是在處理數據時遇到了麻煩。
數據以向量集的形式存在。 每個集合都有一個標簽向量(名稱,它們是字符串)和一組對應的值(雙精度或整數)。
問題是我需要每個數據集在同一列中具有與其他數據集相同的名稱/標簽。 此問題與對向量中的數據進行排序(我知道該怎么做)不同,因為有時某些向量中可能缺少名稱/標簽。
例如:
數據集1:
矢量名稱1 =吉姆,湯姆,瑪麗
向量值1 = 1 2 3
數據集2:
矢量名稱2 =湯姆,瑪麗,瓊
向量值2 = 2 3 4
我想要(偽代碼)一個具有所有可能名稱的名稱向量。 我也希望每個對應的數字向量都以相同的方式排序:
矢量名稱通用=吉姆,瓊,瑪麗,湯姆
向量值Universal1 = 1 0 3 2
矢量值Universal2 = 0 4 3 2
我想做的是拿出一個通用向量,其中包含所有按字母順序排序的標簽/名稱,以及所有相應的也排序的數值數據。
誰能告訴我在c ++中是否有一種優雅的方法來做到這一點? 我想我可以將每個名稱向量的每個元素與每個其他名稱向量的每個元素進行比較,但這似乎很笨拙,我不知道如何將數據放入相應數據向量的正確列中。 感謝您的任何建議。
您要尋找的算法通常稱為“合並”。 基本上,您對兩個數據集進行排序,然后成對查看數據:如果鍵相等,則處理並輸出該對,否則僅處理並前進最小的一對。
您還必須處理兩個列表之一在另一個列表之前結束的情況(可以通過使用保證比您需要處理的任何值都高的特殊標志值來避免這種情況)。
以下是用於合並的偽代碼
vector1
vector2
排序 index1 = index2 = 0;
index1 >= vector1.size()
和index2 >= vector2.size()
(換句話說,直到兩個向量都用完) index1 == vector1.size()
(即,如果vector1
已被處理),則輸出vector2[index2++]
index2 == vector2.size()
(即,如果vector2
已被處理),則輸出vector1[index1++]
vector1[index1] == vector2[index2]
輸出合並的數據並同時增加index1
和index2
vector1[index1] < vector2[index2]
輸出vector1[index1++]
vector2[index2++]
但是,在C ++中,您可以實現一個更容易編寫的解決方案,該解決方案可能仍然足夠快(警告:未經測試的代碼!):
std::map<std::string, int> data1, data2;
std::set<std::string> allkeys;
for (int i=0,n=vector1.size(); i<n; i++)
{
allkeys.insert(vector1[i].name);
data1[vector1[i].name] = vector1[i].value;
}
for (int i=0,n=vector2.size(); i<n; i++)
{
allkeys.insert(vector2[i].name);
data2[vector2[i].name] = vector2[i].value;
}
for (std::set<std::string>::iterator i=allkeys.begin(), e=allkeys.end();
i!=e; ++i)
{
const std::string& key = *i;
std::cout << key << data1[key] << data2[key] << std::endl;
}
這個想法是只構建兩個從名稱到值的映射data1
和data2
,並同時收集出現在名為allkeys
的std::set
鍵中的所有鍵(將相同的名稱多次添加到set中沒有任何作用) 。
在收集階段之后,可以迭代該集合以查找已觀察到的所有名稱,並且對於每個名稱,可以從data1
和data2
映射中檢索值( std::map<std::string, int>
將返回0查找尚未添加到地圖的名稱的值)。
從技術上講,這是一種過度殺傷(使用三個平衡樹來執行只需要兩個排序操作的處理),但是代碼較少,而且無論如何還是可以接受的。
乍看之下,6502的解決方案看起來不錯。 您可能應該在合並部分使用std::merge
。
編輯:
我忘了提到,現在STL的GNU版本中還提供了STL的multiway_merge
擴展。 它是並行模式的一部分,因此它位於命名空間__gnu_parallel
。 如果您需要進行多路合並,那么很難像這樣快速或簡單地使用。
想到的一種快速方法是使用map<pair<string, int>, int>
並為每個值使用右鍵將其存儲在地圖中。 (例如,第一個值集中的(Tom,2)將位於具有值2的鍵(Tom,1)下)。一旦映射准備好,就可以對其進行迭代並構建所需的任何數據結構(假定該映射不足以用於您)。
我認為您需要更改存儲此數據的方式。 您似乎在說每個數字在邏輯上都與相同位置的名稱相關:Jim = 1,Mary = 3,依此類推。
如果是這樣,並且您希望使用某種vector
,則可以像這樣重做數據結構:
typedef std::pair<std::string, int> NameNumberPair;
typedef std::vector<NameNumberPair> NameNumberVector;
NameNumberVector v1;
您需要編寫自己的operator<
,該operator<
根據基礎名稱的排序順序返回。 但是,正如Nawaz指出的那樣, map
將是表示數據關聯性質的一種更好的方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.