如何从列表中提取某些值并将其放入另一个列表中

How to extract certain values from list and put it in another list

本文关键字:列表 另一个 提取      更新时间:2023-10-16

我真的很难做到这一点。我有一个代码块设置,它检查从一个列表到另一个列表的每个值。我希望它如何工作是当两个值是相似的,它应该复制或复制该值到一个完全独立的列表。到目前为止,我所有的努力都失败了。有人能解释一下这件事吗?

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,它仍然快一点。

相关文章: