简体   繁体   English

更新元素 stl 列表列表

[英]Update element stl list of lists

I am working with a list of a list of vector of ints ( std::list<std::list<std::vector<int>>> z(nlevel) ).我正在处理整数向量列表( std::list<std::list<std::vector<int>>> z(nlevel) )的列表。

I might have something like:我可能有这样的事情:

{ {1} {2} {3} }
{ {1 2} {2 1} {1 3} }
{ {1 2 3} {2 1 3} {1 2 4} }

I need to remove the non-unique combination of integers, so eg, the second element of the list above should become我需要删除整数的非唯一组合,例如,上面列表的第二个元素应该变成

{ { 1 2 } {1 3} }

This is a large object, so I'm trying to update each element of the outermost list by reference.这是一个大对象,所以我试图通过引用更新最外层列表的每个元素。 I've tried something like:我试过这样的事情:

lit = z.begin();
for (i = 0; i < nlevel; i++) {
    distinct_z(*lit, primes);
    lit++;
}

where distinct_z is a function to find the unique vector combinations by reference, but this doesn't seem to affect the list z .其中distinct_z是通过引用查找唯一向量组合的函数,但这似乎不会影响列表z Note: distinct_z does work fine in another part of my code where I am already working with the ith element of the list.注意: distinct_z在我的代码的另一部分工作正常,我已经在处理列表的第 i 个元素。 I've provided distinct_z below.我在下面提供了distinct_z It includes some unique data types from the Rcpp package in R, but is hopefully understandable.它包含来自 R 中 Rcpp 包的一些独特数据类型,但希望可以理解。 Essentially, I use the log sum of prime numbers to identify non-unique combinations of integers because the order of the integers does not matter.本质上,我使用素数的对数和来识别整数的非唯一组合,因为整数的顺序无关紧要。 To reiterate, distinct_z does work in another part of my code where I pass it an actual list of vectors of ints.重申一下, distinct_z确实在我的代码的另一部分工作,我向它传递了一个实际的整数向量列表。 The problem seems to be that I'm trying to pass something using an iterator.问题似乎是我试图使用迭代器传递一些东西。

void distinct_lz(std::list<std::vector<int>> &lz,
                      const IntegerVector &primes) {
  int i, j, npids = lz.size();

  NumericVector pids(npids);
  std::list<std::vector<int>>::iterator lit = lz.begin();
  int z_size = lit -> size();
  for(i = 0; i < npids; i++) {
    for (j = 0; j < z_size; j++) {
      // cprime = primes[lit -> at(j)];
      // pids[i] += log(cprime);
      // cprime = primes[lit -> at(j)];
      pids[i] += log(primes[lit -> at(j)]);
    }
    lit++;
  }
  LogicalVector dup = duplicated(round(pids, 8));
  lit = lz.begin();
  for(i = 0; i < npids; i++) {
    if(dup(i) == 1) {
      lz.erase(lit);
    }
    lit++;
  }
}

What is the best approach for doing what I want?做我想做的事的最佳方法是什么?

Background: The data structure probably seems unnecessarily complicated, but I'm enumerating all connected subgraphs starting at a vertex using a breadth-first approach.背景:数据结构可能看起来不必要地复杂,但我正在使用广度优先方法枚举从顶点开始的所有连接子图。 So given a current subgraph, I see what other vertices are connected to create a set of new subgraphs and repeat.因此,给定一个当前子图,我会看到连接了哪些其他顶点以创建一组新子图并重复。 I initially did this using a list of vectors of ints, but removing repeats was ridiculously slow due to the fact that I had to copy the current object if I removed part of the vector.我最初使用整数向量列表来完成此操作,但由于如果删除部分向量,我必须复制当前对象,因此删除重复项的速度非常慢。 This approach is much faster even though the structure is more complicated.尽管结构更复杂,但这种方法要快得多。

Edit: Here is a solution that mostly does what I want, though it results in some undesired copying.编辑:这是一个解决方案,主要是我想要的,尽管它会导致一些不需要的复制。 I updated distinct_z to return a copy of the object instead of modifying the reference, and then replaced the element at lit .我更新了distinct_z以返回对象的副本而不是修改引用,然后替换了lit处的元素。

  lit = z.begin();
  for (i = 0; i < nlevel; i++) {
    (*lit) = distinct_z(*lit, primes);
    lit++;
  }

In C++ there is a well known idiom known as the erase-remove idiom for removing elements from an STL container.在 C++ 中有一个众所周知的习惯用法,称为擦除-删除习惯用法,用于从 STL 容器中删除元素。 It basically involves shuffling unwanted items to the end of the container and then erasing the unwanted tail.它基本上涉及将不需要的项目拖到容器的末端,然后擦除不需要的尾部。

We can use a predicate function (eg lambda) to select the items we want to erase and use functions from <algorithm> .我们可以使用谓词函数(例如 lambda)来选择我们想要删除的项目并使用<algorithm>函数。 In your case we use a set of set of ints ( std::<set<int>> ) to store unique combinations.在您的情况下,我们使用一组整数( std::<set<int>> )来存储独特的组合。 Convert each vector in the list to a set of ints and delete it if hasn't been seen before.将列表中的每个向量转换为一组整数,如果以前没有见过,则将其删除。

#include <set>
#include <list>
#include <vector>
#include <algorithm>
#include <iostream>

void distinct_lz(std::list<std::vector<int>>& lz)
{
    std::set<std::set<int>> unqiueNums;

    lz.erase(std::remove_if(lz.begin(), lz.end(),
        [&unqiueNums](std::vector<int>& v) {
            std::set<int> s{ v.cbegin(), v.cend() };
            if (unqiueNums.find(s) != unqiueNums.end())
                return true;
            else
            {
                unqiueNums.insert(s);
                return false;
            }
        }), lz.end());

}

int main()
{
    std::list<std::vector<int>> lv = { {1, 2}, {2, 1}, {1, 3}, {3,4} };
    distinct_lz(lv);
    for (auto &v: lv)
    {
        for( auto n: v)
        {
            std::cout << n << " ";
        }

        std::cout << "\n";
    }
}

Output:输出:

1 2 1 2
1 3 1 3
3 4 3 4

Working version here .工作版本在这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM