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

时间:2014-06-03 13:15:13

标签: c++ list iterator copy

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

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;
  }

4 个答案:

答案 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!祝你好运!