C ++中两个地图之间的同时并集和交集
Simultaneous Union and Intersection between two maps in C++
在做一个大学项目时,我遇到了以下问题:
我有两个映射(Kmer1 和 Kmer2),它们由一个字符串(键)和一个整数(值)组成。
我必须计算遵循此公式的 距离
[1-(I/U)]*100
Where...
...U = the sum of all int values inside Kmer1 U Kmer2
...I = the sum of all int values inside Kmer1 ∩ Kmer2
Consider that...
... The U and ∩ are made evaluating the keys (strings)
... When an element is in both maps:
- At the Union we add the one with higher int value
- At the Intersection we add the one with lower int value
示例:
Kmer1 = AAB¹ AAC¹ AAG³
Kmer2 = AAG¹ AAT² ABB¹
Union = AAB¹ AAC¹ AAG³ AAT² ABB¹ U= 8
Intersection = AAG¹ I= 1
Distance = 87.5
代码时间!
我一直在努力解决它,但所有的解决方案都是......部分正确,
并非所有情况都包括在内。所以当我试图覆盖它们时,我以无限循环结束,异常上升,长长的 if-else 嵌套(太糟糕了..)无论如何,这是最不糟糕和无效的尝试:
设置:
Species::Kmer Kmer1, Kmer2; //The two following lines get the Kmer from another
Kmer1 = esp1->second.query_kmer(); //object.
Kmer2 = esp2->second.query_kmer();
Species::Kmer::const_iterator it1, it2, last1, last2;
it1 = Kmer1.cbegin(); //Both Kmer are maps, therefore they are ordered and
it2 = Kmer2.cbegin(); //whitout duplicates.
last1 = --Kmer1.cend();
last2 = --Kmer2.cend();
double U, I;
U = I = 0;
应用公式的循环:
while (it1 != Kmer1.cend() and it2 != Kmer2.cend()){
if (it1->first == it2->first) {
if (it1->second > it2->second) {
U += it1->second;
I += it2->second;
} else {
U += it2->second;
I += it1->second;
}
++it1;
++it2;
} else if (it1->first < it2->first) {
U += it1->second;
++it1;
} else {
U += it2->second;
++it2;
}
}
请注意,我没有先创建并集和交集,然后计算每个的总和,而是直接跳到值的总和。我知道也许这并不难,但我一直在努力解决它,但我几乎被困住了......
I've uploaded the whole code at Github: (Maybe it helps)
- There is a makefile to build the code
- There is a file called input.txt with a sample for this specific problem
- Also inside the input.txt, after line13 (fin) I've added the expected output
- Executing ./program.exe < input.txt should be enough to test it.
https://github.com/PauGalopa/Cpp-Micro-Projects/tree/master/Release
重要
是的!我知道几乎所有可以在几行中完成此操作的 STL 功能,但是......
由于这是一个大学项目,我受教学大纲的限制,所以请考虑我只被允许使用 "map" "string" "vector" 和其他一些。
不,我不能使用 "algorithm"(我真的希望我可以)
我会在评论中澄清关于我可以做什么或使用哪些事情的任何疑问。
在主 while 循环之后添加这两个循环。
while (it1 != Kmer1.cend()){
U += it1->second;
it1++;
}
while (it2 != Kmer2.cend()){
U += it2->second;
it2++;
}
unordered_mapping
的一种稍微更简洁的方法,但仍适用于 mapping
的方法是将 Kmer1
的所有元素添加到 U
和共享元素至 I
。然后将Kmer2
的所有未共享元素添加到U
:
for(it1 = Kmer1.cbegin(); it1 != Kmer1.cend(); it1++) {
auto other = Kmer2.find(it1->first);
if(other == Kmer2.cend()) {
U += it1->second;
} else {
U += max(it1->second, other->second);
I += min(it1->second, other->second);
}
}
for(it2 = Kmer2.cbegin(); it2 != Kmer2.cend(); it2++) {
if(Kmer1.count(it2->first) == 0) {
U += it2->second
}
}
对于正确实施的 unordered_mapping
(散列 table),find
操作将是 O(1)
,而不是 O(log(n)
,使其更快一些.
这个循环应该有效:
while ( true ){
bool end1 = it1 == Kmer1.cend();
bool end2 = it2 == Kmer2.cend();
if( end1 and end2 )
break;
if( end2 or it1->first < it2->first ) {
U += (it1++)->second;
continue;
}
if( end1 or it2->first < it1->first ) {
U += (it2++)->second;
continue;
}
auto p = std::minmax( (it1++)->second, (it2++)->second );
I += p.first;
U += p.second;
}
这是一个相当简单的解决方案,只使用 std::map
的一些属性,没有迭代器。我希望你被允许使用这种解决方案。
#include <iostream>
#include <map>
#include <string>
int main () {
std::map <std::string, int> A = {{"AAB", 1}, {"AAC", 1}, {"AAG", 3}};
std::map <std::string, int> B = {{"AAG", 1}, {"AAT", 2}, {"ABB", 1}};
std::map <std::string, int> Union;
int sum_A = 0, sum_B = 0, sum_Union = 0, sum_Inter = 0;;
for (auto &x: A) {
Union[x.first] = std::max (Union[x.first], x.second);
sum_A += x.second;
}
for (auto &x: B) {
Union[x.first] = std::max (Union[x.first], x.second);
sum_B += x.second;
}
for (auto &x: Union) {
sum_Union += x.second;
}
sum_Inter = sum_A + sum_B - sum_Union;
double distance = 100.0 * (1.0 - double(sum_Inter)/sum_Union);
std::cout << "sum_Union = " << sum_Union << " sum_Inter = " << sum_Inter << "\n";
std::cout << "Distance = " << distance << "\n";
}
在做一个大学项目时,我遇到了以下问题: 我有两个映射(Kmer1 和 Kmer2),它们由一个字符串(键)和一个整数(值)组成。 我必须计算遵循此公式的 距离
[1-(I/U)]*100
Where...
...U = the sum of all int values inside Kmer1 U Kmer2
...I = the sum of all int values inside Kmer1 ∩ Kmer2
Consider that...
... The U and ∩ are made evaluating the keys (strings)
... When an element is in both maps:
- At the Union we add the one with higher int value
- At the Intersection we add the one with lower int value
示例:
Kmer1 = AAB¹ AAC¹ AAG³
Kmer2 = AAG¹ AAT² ABB¹
Union = AAB¹ AAC¹ AAG³ AAT² ABB¹ U= 8
Intersection = AAG¹ I= 1
Distance = 87.5
代码时间! 我一直在努力解决它,但所有的解决方案都是......部分正确, 并非所有情况都包括在内。所以当我试图覆盖它们时,我以无限循环结束,异常上升,长长的 if-else 嵌套(太糟糕了..)无论如何,这是最不糟糕和无效的尝试:
设置:
Species::Kmer Kmer1, Kmer2; //The two following lines get the Kmer from another
Kmer1 = esp1->second.query_kmer(); //object.
Kmer2 = esp2->second.query_kmer();
Species::Kmer::const_iterator it1, it2, last1, last2;
it1 = Kmer1.cbegin(); //Both Kmer are maps, therefore they are ordered and
it2 = Kmer2.cbegin(); //whitout duplicates.
last1 = --Kmer1.cend();
last2 = --Kmer2.cend();
double U, I;
U = I = 0;
应用公式的循环:
while (it1 != Kmer1.cend() and it2 != Kmer2.cend()){
if (it1->first == it2->first) {
if (it1->second > it2->second) {
U += it1->second;
I += it2->second;
} else {
U += it2->second;
I += it1->second;
}
++it1;
++it2;
} else if (it1->first < it2->first) {
U += it1->second;
++it1;
} else {
U += it2->second;
++it2;
}
}
请注意,我没有先创建并集和交集,然后计算每个的总和,而是直接跳到值的总和。我知道也许这并不难,但我一直在努力解决它,但我几乎被困住了......
I've uploaded the whole code at Github: (Maybe it helps)
- There is a makefile to build the code
- There is a file called input.txt with a sample for this specific problem
- Also inside the input.txt, after line13 (fin) I've added the expected output
- Executing ./program.exe < input.txt should be enough to test it.
https://github.com/PauGalopa/Cpp-Micro-Projects/tree/master/Release
重要 是的!我知道几乎所有可以在几行中完成此操作的 STL 功能,但是...... 由于这是一个大学项目,我受教学大纲的限制,所以请考虑我只被允许使用 "map" "string" "vector" 和其他一些。 不,我不能使用 "algorithm"(我真的希望我可以) 我会在评论中澄清关于我可以做什么或使用哪些事情的任何疑问。
在主 while 循环之后添加这两个循环。
while (it1 != Kmer1.cend()){
U += it1->second;
it1++;
}
while (it2 != Kmer2.cend()){
U += it2->second;
it2++;
}
unordered_mapping
的一种稍微更简洁的方法,但仍适用于 mapping
的方法是将 Kmer1
的所有元素添加到 U
和共享元素至 I
。然后将Kmer2
的所有未共享元素添加到U
:
for(it1 = Kmer1.cbegin(); it1 != Kmer1.cend(); it1++) {
auto other = Kmer2.find(it1->first);
if(other == Kmer2.cend()) {
U += it1->second;
} else {
U += max(it1->second, other->second);
I += min(it1->second, other->second);
}
}
for(it2 = Kmer2.cbegin(); it2 != Kmer2.cend(); it2++) {
if(Kmer1.count(it2->first) == 0) {
U += it2->second
}
}
对于正确实施的 unordered_mapping
(散列 table),find
操作将是 O(1)
,而不是 O(log(n)
,使其更快一些.
这个循环应该有效:
while ( true ){
bool end1 = it1 == Kmer1.cend();
bool end2 = it2 == Kmer2.cend();
if( end1 and end2 )
break;
if( end2 or it1->first < it2->first ) {
U += (it1++)->second;
continue;
}
if( end1 or it2->first < it1->first ) {
U += (it2++)->second;
continue;
}
auto p = std::minmax( (it1++)->second, (it2++)->second );
I += p.first;
U += p.second;
}
这是一个相当简单的解决方案,只使用 std::map
的一些属性,没有迭代器。我希望你被允许使用这种解决方案。
#include <iostream>
#include <map>
#include <string>
int main () {
std::map <std::string, int> A = {{"AAB", 1}, {"AAC", 1}, {"AAG", 3}};
std::map <std::string, int> B = {{"AAG", 1}, {"AAT", 2}, {"ABB", 1}};
std::map <std::string, int> Union;
int sum_A = 0, sum_B = 0, sum_Union = 0, sum_Inter = 0;;
for (auto &x: A) {
Union[x.first] = std::max (Union[x.first], x.second);
sum_A += x.second;
}
for (auto &x: B) {
Union[x.first] = std::max (Union[x.first], x.second);
sum_B += x.second;
}
for (auto &x: Union) {
sum_Union += x.second;
}
sum_Inter = sum_A + sum_B - sum_Union;
double distance = 100.0 * (1.0 - double(sum_Inter)/sum_Union);
std::cout << "sum_Union = " << sum_Union << " sum_Inter = " << sum_Inter << "\n";
std::cout << "Distance = " << distance << "\n";
}