- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
如何有效地将对象(或一系列对象)从 vector A 复制到 vector B,
其中 vector B 已经包含与 vector A 中相同的某些对象,
以便从 vector A 复制的对象没有在 vector B 中列出?
我有一个图存储为 std::vector<MinTreeEdge>minTreeInput
中的边 vector .
我有一个根据这个图创建的最小生成树,存储在 std::vector<MinTreeEdge>minTreeOutput
中.
我正在尝试将一定数量的边随机添加回 minTreeOutput
.为此,我想从 minTreeInput
复制元素回minTreeOutput
直到后者包含所需数量的边。当然,复制过来的每个边缘对象都必须尚未存储 minTreeOutput
.此图中不能有重复边。
以下是我到目前为止的想法。它有效,但它确实很长,而且我知道循环必须运行多次,具体取决于图形和树。我想知道如何正确执行此操作:
// Edge class
struct MinTreeEdge
{
// For std::unique() between objects
bool operator==(MinTreeEdge const &rhs) const noexcept
{
return lhs == rhs.lhs;
}
int lhs;
int node1ID;
int node2ID;
int weight;
......
};
......
// The usage
int currentSize = minTreeOutput.size();
int targetSize = currentSize + numberOfEdgesToReturn;
int sizeDistance = targetSize - currentSize;
while(sizeDistance != 0)
{
//Probably really inefficient
for(std::vector<MinTreeEdge>::iterator it = minTreeInput.begin(); it != minTreeInput.begin()+sizeDistance; ++it)
minTreeOutput.push_back(*it);
std::vector<MinTreeEdge>::iterator mto_it;
mto_it = std::unique (minTreeOutput.begin(), minTreeOutput.end());
currentSize = minTreeOutput.size();
sizeDistance = targetSize - currentSize;
}
或者,有没有办法只列出 minTreeInput
中的所有边? (图)不在minTreeOutput
中(树)而不必检查前者与后者中的每个单独元素?
最佳答案
How can I efficiently copy objects (or a range of objects) from vector A into vector B, where vector B already contains certain objects identical to those from vector A, so that no objects copied from vector A are already listed in vector B?
如果我正确理解了这个问题,这可以解释为“我如何创建两个 vector 的集合并集?”。
答案:使用std::set_union
请注意,要使其正常工作,需要对两个 vector 进行排序。正如您已经提到的那样,这是出于效率原因。
#include <vector>
#include <algorithm>
#include <cassert>
#include <iterator>
struct MinTreeEdge
{
// For std::unique() between objects
bool operator==(MinTreeEdge const &rhs) const noexcept
{
return lhs == rhs.lhs;
}
int lhs;
int node1ID;
int node2ID;
int weight;
};
struct lower_lhs
{
bool operator()(const MinTreeEdge& l, const MinTreeEdge& r) const noexcept
{
return l.lhs < r.lhs;
}
};
std::vector<MinTreeEdge> merge(std::vector<MinTreeEdge> a,
std::vector<MinTreeEdge> b)
{
// let's pessimistically assume that the inputs are not sorted
// we could simply assert that they are if the caller is aware of
// the requirement
std::sort(a.begin(), a.end(), lower_lhs());
std::sort(b.begin(), b.end(), lower_lhs());
// alternatively...
// assert(std::is_sorted(a.begin(), a.end(), lower_lhs()));
// assert(std::is_sorted(b.begin(), b.end(), lower_lhs()));
// optional step if the inputs are not already `unique`
a.erase(std::unique(a.begin(), a.end()), a.end());
b.erase(std::unique(b.begin(), b.end()), b.end());
std::vector<MinTreeEdge> result;
result.reserve(a.size() + b.size());
std::set_union(a.begin(), a.end(),
b.begin(), b.end(),
std::back_inserter(result),
lower_lhs());
return result;
}
int main()
{
// example use case
auto a = std::vector<MinTreeEdge>{};
auto b = std::vector<MinTreeEdge>{};
b = merge(std::move(a), std::move(b));
}
已经提到了集合来实现这一点。可以公平地说,如果:
MinTreeEdge
复制成本高 并且,然后我们可以期望看到使用 unordered_set
的性能优势。但是,如果对象复制成本很高,那么我们可能希望通过引用将它们存储在我们的临时集中。
我可能会这样做:
// utility class which converts unary and binary operations on
// a reference_wrapper into unary and binary operations on the
// referred-to objects
template<class unary, class binary>
struct reference_as_object
{
template<class U>
decltype(auto) operator()(const std::reference_wrapper<U>& l) const {
return _unary(l.get());
}
template<class U, class V>
decltype(auto) operator()(const std::reference_wrapper<U>& l,
const std::reference_wrapper<V>& r) const {
return _binary(l.get(), r.get());
}
unary _unary;
binary _binary;
};
// utility to help prevent typos when defining a set of references
template<class K, class H, class C> using unordered_reference_set =
std::unordered_set<
std::reference_wrapper<K>,
reference_as_object<H, C>,
reference_as_object<H, C>
>;
// define unary and binary operations for our set. This way we can
// avoid polluting MinTreeEdge with artificial relational operators
struct mte_hash
{
std::size_t operator()(const MinTreeEdge& mte) const
{
return std::hash<int>()(mte.lhs);
}
};
struct mte_equal
{
bool operator()(MinTreeEdge const& l, MinTreeEdge const& r) const
{
return l.lhs == r.lhs;
}
};
// merge function. arguments by value since we will be moving
// *expensive to copy* objects out of them, and the vectors themselves
// can be *moved* into our function very cheaply
std::vector<MinTreeEdge> merge2(std::vector<MinTreeEdge> a,
std::vector<MinTreeEdge> b)
{
using temp_map_type = unordered_reference_set<MinTreeEdge, mte_hash, mte_equal>;
// build a set of references to existing objects in b
temp_map_type tmap;
tmap.reserve(b.capacity());
// b first, since the requirements mentioned 'already in B'
for (auto& ob : b) { tmap.insert(ob); }
// now add missing references in a
for (auto& oa : a) { tmap.insert(oa); }
// now build the result, moving objects from a and b as required
std::vector<MinTreeEdge> result;
result.reserve(tmap.size());
for (auto r : tmap) {
result.push_back(std::move(r.get()));
}
return result;
// a and b now have elements which are valid but in an undefined state
// The elements which are defined are the duplicates we don't need
// on summary, they are of no use to us so we drop them.
}
假设我们想坚持使用 vector 方法(我们几乎总是应该这样做),但是 MinTreeEdge 的复制成本有点高。假设它使用 pimpl 惯用语来实现内部多态性,这将不可避免地意味着在复制时分配内存。但是,假设它可以廉价移动。我们还假设不能期望调用者在将数据发送给我们之前对数据进行排序或唯一化。
我们仍然可以使用标准算法和 vector 实现良好的效率:
std::vector<MinTreeEdge> merge(std::vector<MinTreeEdge> a,
std::vector<MinTreeEdge> b)
{
// sorts a range if not already sorted
// @return a reference to the range
auto maybe_sort = [] (auto& c) -> decltype(auto)
{
auto begin = std::begin(c);
auto end = std::end(c);
if (not std::is_sorted(begin, end, lower_lhs()))
std::sort(begin, end, lower_lhs());
return c;
};
// uniqueify a range, returning the new 'end' of
// valid data
// @pre c is sorted
// @return result of std::unique(...)
auto unique = [](auto& c) -> decltype(auto)
{
auto begin = std::begin(c);
auto end = std::end(c);
return std::unique(begin, end);
};
// turn an iterator into a move-iterator
auto mm = [](auto iter) { return std::make_move_iterator(iter); };
std::vector<MinTreeEdge> result;
result.reserve(a.size() + b.size());
// create a set_union from two input containers.
// @post a and b shall be in a valid but undefined state
std::set_union(mm(a.begin()), mm(unique(maybe_sort(a))),
mm(b.begin()), mm(unique(maybe_sort(b))),
std::back_inserter(result),
lower_lhs());
return result;
}
如果提供一个自由函数 void swap(MinTreeEdge& l, MinTreeEdge& r) nothrow
那么这个函数将需要恰好 N 次移动,其中 N 是结果集的大小。由于在 pimpl 类中,移动只是指针交换,因此该算法仍然有效。
关于c++ - 如何有效地将唯一对象从一个 vector 复制到另一个 vector (由相同对象的子集组成)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39067933/
我收到未知数据,我想以编程方式查看相关性,并将所有完全相关的变量组合在一起(忽略方向)。在下面的数据集中,我可以手动查看相关性并说 a, f, g, h一起去吧b, d, e .我怎样才能以编程方
这个问题在这里已经有了答案: use dplyr's summarise_each to return one row per function? (3 个答案) 关闭 4 年前。 作为探索性工作的
我想要完成的是使用数组存储未知大小的多项式。我在互联网上看到的是使用一个数组,每个单元格都包含系数,度数是单元格编号,但这不是有效的,因为如果我们有一个多项式,如:6x^14+x+5。这意味着我们将从
嘿伙计们,我一直在尝试解析 HTML 文件以从中抓取文本,但时不时地,我会得到一些非常奇怪的字符,例如 à€œ。我确定是“智能引号”或弯头标点符号导致了我的所有问题,因此我的临时修复是搜索所有这些字符
我原来的 data.table 由三列组成。 site、observation_number 和 id。 例如以下是 id = z 的所有观察结果 |site|observation_number|i
"Premature optimisation is the root of all evil (but it's nice to have once you have an ugly solutio
给定这个数组 X: [1 2 3 2 3 1 4 5 7 1] 和行长度数组R: [3 2 5] 表示转换后每行的长度。 我正在寻找一个计算效率高的函数来将 X reshape 为数组 Y: [[ 1
我有一些 data.frame s: # Sample data a <- data.frame(c(1:10), c(11:20)) names(a) <- c("A", "B") b <- dat
我有点困惑。列表擅长任意位置插入,但不善于随机访问? (怎么可能)如果你不能随机访问,你怎么知道在哪里插入? 同样,如果你可以在任何位置插入,为什么你不能从那个位置高效地读取? 最佳答案 如果您已经有
我有一个向量,我想计算它的移动平均值(使用宽度为 5 的窗口)。 例如,如果有问题的向量是[1,2,3,4,5,6,7,8],那么 结果向量的第一个条目应该是 [1,2,3,4,5] 中所有条目的总和
有一个随机整数生成器,它生成随机整数并在后台运行。需求设计一个API,调用时返回当时的簇数。 簇:簇是连续整数的字典顺序。例如,在这种情况下,10,7,1,2,8,5,9 簇是 3 (1,2--5--
我想做的是将一组 (n) 项分成大小相等的组(大小为 m 的组,并且为简单起见,假设没有剩余,即 n 可以被 m 整除)。这样做多次,我想确保同一组中的任何项目都不会出现两次。 为了使这稍微更具体一些
假设我有一些包含类型排列的模板表达式,在本例中它们来自 Abstract Syntax Tree : template
我已经在这方面工作了几天,似乎没有我需要的答案。 由于担心这个被标记为重复,我将解释为什么其他问题对我不起作用。 使用 DIFFLIB for Python 的任何答案都无助于我的需求。 (我在下面描
我正在使用 NumPy 数组。 我有一个 2N 长度向量 D,并希望将其一部分 reshape 为 N x N 数组 C. 现在这段代码可以满足我的要求,但对于较大的 N 来说是一个瓶颈: ``` i
我有一个问题: 让我们考虑这样的 pandas 数据框: Width Height Bitmap 67 56 59 71 61 73 ...
我目前正在用 C 语言编写一个解析器,设计它时我需要的东西之一是一个可变字符串“类”(一组对表示实例的不透明结构进行操作的函数),我将其称为 my_string。 string 类的实例只不过是包装
假设我在 --pandas-- 数据框中有以下列: x 1 589 2 354 3 692 4 474 5 739 6 731 7 259 8 723
我有一个成员函数,它接受另一个对象的常量引用参数。我想 const_cast 这个参数以便在成员函数中轻松使用它。为此,以下哪个代码更好?: void AClass::AMember(const BC
我们目前正在将 Guava 用于其不可变集合,但我惊讶地发现他们的 map 没有方法可以轻松创建只需稍作修改的新 map 。最重要的是,他们的构建器不允许为键分配新值或删除键。 因此,如果我只想修改一
我是一名优秀的程序员,十分优秀!