我很难做到这一点。我有一个代码块设置,它检查从一个列表到另一个列表的每个值。我希望它如何工作是当两个值相似时,它应该将该值复制或复制到一个完全独立的列表中。到目前为止,我所有的努力都失败了有人可以就这件事情说清楚吗?
void compare_list_warning(list<string>*list_one,list<string>*list_two)
{
cout << "Made a function call!!!" << endl;
list<string> duplicates;
string line;
string *ptline = &line;
list<string>::iterator pt1 = list_one->begin();
cout << "About to compare the lists" << endl;
for (int x = 0; x < list_one->size(); ++x)
{
list<string>::iterator pt2 = list_two->begin();
for (int x = 0; x < list_two->size(); ++x)
{
if (*pt1 == *pt2)
{
*pt1 = *ptline;
duplicates.push_back(line);
}
else
{
++pt2;
}
}
++pt1;
}
答案 0 :(得分:1)
我希望它如何工作是当两个值相似时 将该值复制或复制为完全独立的值 列表。
当你可以直接翻译成C ++时,你会使用不必要的变量和指针使事情变得复杂。
根据您的描述,您需要一个带有两个字符串列表的函数,并返回两个输入列表中存在的字符串列表。
即,
list<string> duplicates(list<string> list_one, list<string> list_two)
{
我们需要一个单独的列表才能从函数返回。
list<string> duplicates;
这是我们需要的所有变量。
现在,遍历两个列表寻找重复项
您用于迭代的x
没有任何实际用途,也会造成混淆
让我们使用更惯用的迭代器循环。
list_one
for (list<string>::iterator p1 = list_one.begin(); p1 != list_one.end(); ++p1)
{
浏览list_two
for (list<string>::iterator p2 = list_two.begin(); p2 != list_two.end(); ++p2)
{
如果两个项目相同,则将其中一个添加到duplicates
列表中。
if (*pt1 == *pt2)
{
duplicates.push_back(*pt1);
}
}
}
当您查看所有内容时,请返回结果
return duplicates;
}
(你在这里有一个错误,你用list_one
覆盖了{{1}}中的当前项而不是相反的方式。
此外,如果您没有找到匹配项,则只升级迭代器。)
答案 1 :(得分:1)
这是一个集合交叉问题。
我尝试尽可能优化代码。这将在O(N+M)
上运行,其中M,N
分别是您的集合的大小。
这在C++11
#include <iostream>
#include <string>
#include <unordered_set>
#include <list>
#include <algorithm>
using namespace std;
list<string> compare_list_warning(list<string> const& list_one, list<string> const& list_two)
{
list<string> const& small_list = list_one.size() < list_two.size() ? list_one : list_two;
list<string> const& big_list = list_one.size() < list_two.size() ? list_two : list_one;
list<string> duplicates;
unordered_set<string> duplicate_finder;
duplicate_finder.insert(begin(small_list), end(small_list));
copy_if(
begin(big_list), end(big_list)
, back_inserter(duplicates)
, [&](string const& v) {
return (duplicate_finder.find(v) != end(duplicate_finder));
}
);
return duplicates;
}
int main() {
list<string> common_names =
compare_list_warning(
{"one", "two", "three", "four"}
, {"three", "one", "five", "xx", "two"}
);
for(string const& common : common_names)
std::cout << common << "\t";
return 0;
}
您的输出来自GCC 4.9或Clang 3.4:
three one two
答案 2 :(得分:0)
molbdnilo 回答非常简单。
这是一种过度的方法(仅限C ++ 11)。它应该在庞大的数据集上表现更好。代码保持很小。你也可以实现&#34;类似&#34;的逻辑。通过提供除std::less
以外的比较函数的元素。
#include <iostream>
#include <string>
#include <set>
#include <unordered_set>
#include <list>
#include <algorithm>
using namespace std;
template <typename T> using intersection_set = set<reference_wrapper<T const>, less<T>>;
list<string> compare_list_warning(list<string> const& list_one, list<string> const& list_two)
{
intersection_set<string> set_one, set_two;
set_one.insert(begin(list_one), end(list_one));
set_two.insert(begin(list_two), end(list_two));
list<string> output;
set_intersection(begin(set_one), end(set_one), begin(set_two), end(set_two), back_inserter(output), less<string>());
return output;
}
int main() {
list<string> common_names = compare_list_warning({"Roger", "Marcel", "Camille", "Hubert"}, {"Huguette", "Cunegond", "Marcelle", "Camille"});
for(string const& common : common_names) {
std::cout << "Common element: " << common << "\n";
}
std::cout << std::flush;
return 0;
}
修改强>
AK _ 答案在复杂性方面很有意思,不过我会这样写:
list<string> compare_list_warning(list<string> const& list_one, list<string> const& list_two)
{
list<string> const& small_list = list_one.size() < list_two.size() ? list_one : list_two;
list<string> const& big_list = list_one.size() < list_two.size() ? list_two : list_one;
list<string> duplicates;
unordered_set<string> duplicate_finder;
duplicate_finder.reserve(small_list.size());
duplicate_finder.insert(begin(small_list), end(small_list));
copy_if(begin(big_list), end(big_list), back_inserter(duplicates), [&](string const& v) { return (duplicate_finder.find(v) != end(duplicate_finder)); });
return duplicates;
}
编辑2
AK _ 的算法是最快的。经过性能测试,它比我的快10倍。您可以找到性能测试here的完整代码。如果您需要避免碰撞风险,可以使用set
代替unordered_set
,它仍然会更快。
答案 3 :(得分:0)
这里我生成了两个列表(如您所见,然后比较它们的值)。程序将公共值存储在“common_list”中,您可以通过打印这些值来查看。现在,你可以操纵这些线来获得你想要的任何东西!
#include <iostream>
#include <list>
#include <string>
using namespace std;
void compare_list_warning(list<string>list_one, list<string>list_two);
int main()
{
list <string> list1;
list <string> list2;
list1.push_back("hi");
list1.push_back("there");
list1.push_back("I am");
list1.push_back("abc");
list2.push_back("hello");
list2.push_back("something_random");
list2.push_back("there");
list2.push_back("greetings");
list2.push_back("cheers");
compare_list_warning(list1, list2); //here calling the function
system("pause");
return 0;
}
//defining the function here
void compare_list_warning(list<string>list_one, list<string>list_two)
{
list<string> ::iterator pt1 = list_one.begin();
list<string> ::iterator pt2 = list_two.begin();
list<string> common_list;
for (int i = 0; i < list_one.size(); ++i)
{
for (int j = 0; j < list_two.size(); ++j)
{
if (*pt1 == *pt2)
{
common_list.push_back(*pt1);
}
++pt2;
}
pt2 = list_two.begin(); //this is important; reset the iterator
++pt1;
}
list<string> ::iterator pt3 = common_list.begin();
cout << "Here is list of common values: " << endl;
for (int i = 0; i < common_list.size(); ++i)
{
cout << *pt3 << endl;
++pt3;
}
}
// bingo! it prints "there"
我想,这里的重点是重置迭代器pt2!祝你好运!