如何从列表中提取某些值并将其放入另一个列表中
How to extract certain values from list and put it in another list
我真的很难做到这一点。我有一个代码块设置,它检查从一个列表到另一个列表的每个值。我希望它如何工作是当两个值是相似的,它应该复制或复制该值到一个完全独立的列表。到目前为止,我所有的努力都失败了。有人能解释一下这件事吗?
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;
}
我希望它如何工作是当两个值是相似的,它应该将该值复制或复制到完全独立的列表。
当你可以直接转换成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;
}
(你在这里有一个bug,你用空字符串而不是相反的方式覆盖list_one
中的当前项目。而且,只有在没有找到匹配项时才推进迭代器)
这是一个集合交叉问题。
我尝试尽可能优化代码。这将在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
我在这里生成了两个列表(如您所见,然后比较了它们的值)。程序将公共值存储在"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!好运!
molbdnilo答案很好很简单
这里有一种夸张的方法(仅限c++ 11)。它应该在庞大的数据集上表现得更好。代码保持非常小。您还可以通过提供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倍左右。您可以在这里找到性能测试的完整代码。如果您需要避免碰撞风险,可以使用set
代替unordered_set
,它仍然快一点。
- 链表,将列表复制到另一个列表
- 我如何创建一个列表,然后从中创建两个列表,其中一个用于偶数,另一个用于奇数?
- 如何将列表从一个类复制到另一个类
- 将列表的对象C++移动到另一个对象
- 通过另一个宏创建的函数创建所有列表的宏
- 在由邻接列表表示的树中查找节点到另一个给定节点之间的路径
- 如何制作一个结构程序,在其中可以存储无限量的数据,以便每次您想要时都可以将另一个产品添加到列表中?
- 让构造函数在其初始化列表中调用同一类的另一个构造函数是否有效
- 一种体面的方式来转换const列表参考参数,然后传递到另一个函数
- 将元素从一个向量复制到另一个向量的最有效方法,给定一个不被复制的索引列表
- 维护多集中数字的排序列表和另一个集合中的累积总和
- 将带有指针的 STD 列表复制到另一个带有指针的 STD 列表
- 比较一个链接列表与另一个黑名单与词频列表C++
- 从文本文件将整数读入简单的链表中.然后对整数列表进行气泡排序并读出到另一个文件
- 在 std 列表中查找对象并将其添加到另一个列表
- 将类的实例传递给另一个构造函数,该构造函数将其对象添加到所传递实例所拥有的列表中
- 在c++中遍历一个列表并在另一个列表中搜索每个元素
- 如何将参数列表传递给c++中的另一个函数
- 如何通过赋值运算符重载将一个列表复制到另一个列表上?C++
- 通过初始化列表调用另一个类的构造函数.有问题