是否有方便的方法从值(在某个时间间隔内)的向量(或其他stl容器)中删除项目?
例如:我得到了一个带浮点值的向量
1.1 1.3 2.2 3.2 4.1 5.2 5.1 1.1 8.0 2.1
和delta为0.2,这将导致以下结果
1.1 2.2 3.2 4.1 5.1 8.0
因此删除增量内的所有“重复”项目并保留该范围内的一个值。 可以假设这些值是“聚集的”,其中这些值之间的差异大于3 * delta。只应保留群集的一个值(平均值),应删除群集中的所有其他值。
当然,可以使用嵌套循环进行迭代,但这看起来很复杂,因为迭代器的变化,所以我想到了一种更方便的方法。我找到了remove_if,但是这个函数不能“比较”。
感谢您的建议。
答案 0 :(得分:7)
您可以将std::unique
与谓词一起使用:
template <typename It, typename Predicate>
It unique(It first, It last, Predicate pred);
最常用的std::unique
形式不带谓词,只删除序列中的重复项。但是你可以编写一个实现你的过滤器(在你的情况下,使用间隙比较两个值)并设置。类似的东西:
bool CompareWithGap(double a, double b)
{
return abs(a - b) <= 0.2;
}
并使用它来拨打std::unique
:
auto it = std::unique(v.begin(), v.end(), CompareWithGap);
v
是你的向量(或任何其他序列)。
编辑:忘记提及您需要在使用std::unique
之前对序列进行排序。如果这不是一个选项,你必须编写自己的算法。
第二次编辑:完成后,正如Christian Rau在评论中指出的那样,您现在可以使用erase
方法删除序列中删除的项目:
v.erase(it, v.end());
答案 1 :(得分:6)
你的问题实际上非常复杂,因为“范围内的一个值”没有明确定义。比如给出
1.1 1.2 1.3
你要保留哪个?大概是第一个,即1.1。好了,现在怎么样0.9 1.1 1.3
遵循第一条规则,我们保持0.9和1.3,但我们可以只保留1.1。我认为的问题是0.9和1.3'重复'还是没有?我认为你已经很好地定义了这个。
这种情况怎么样,1.1 1.2 1.3 1.4 1.5 1.6?所有值都在另一个值的0.2之内,但并非所有值都在每个其他值的0.2之内。那么它们都是重复的吗?或者你需要拆分它们吗?如果是这样,他们应该如何分开,或许选择1.1和1.4?
所以我想在你更准确地定义问题之前,你不可能编写代码或帮助我们。
您可能需要查看disjoint-set data structure。根据您正在尝试做的事情,它可能是解决此问题的最有效方法。
答案 2 :(得分:0)
您可以在迭代现有向量并填充所需数据的同时创建新向量吗?然后,您可以删除旧向量并返回对新向量的引用。
答案 3 :(得分:0)
如果你想要的是保留第一个项目(因此如果你有0.9,1.1和1.3你保持0.9和1.3)那么你的谓词应该是一个类。
理想情况下,您的课程应该如下所示:
class IsWithinRange
{
std::set< double > values;
double tolerance;
public:
explicit IsWithinRange( double tol ) : tolerance( tol )
{
}
bool operator()( double val )
{
std::set< double >::iterator iter = values.lower_bound( val );
if( iter != values.end() )
{
if( *iter - val < tolerance )
{
return false;
}
}
if( iter != values.begin() )
{
--iter;
if( val - *iter < tolerance )
{
return false;
}
}
values.insert( val );
return true;
}
};
它应该作为std::remove_if
的仿函数谓词类,但它可能会复制内部std :: set的次数超过你想要的次数,所以你可以尝试“优化”,如果你认为你需要。 (使用集合创建它虽然相当具有侵入性,但您也可以指定remove_if的第3个模板参数来指示引用而不是依赖于演绎)。请注意谓词operator()是非const的。