如果N> =列表大小(并且也处理N = 0),获取std :: list的前N个元素或整个列表的新列表的正确和安全的方法是什么?获取std :: list的前N个元素?
更新
其实我并不需要一个新的列表,我只是想在后面的代码列表的子集进行操作。我假设创建一个新列表是一个合理的方式来做到这一点(注意列表大小通常在50以下)。
如果N> =列表大小(并且也处理N = 0),获取std :: list的前N个元素或整个列表的新列表的正确和安全的方法是什么?获取std :: list的前N个元素?
更新
其实我并不需要一个新的列表,我只是想在后面的代码列表的子集进行操作。我假设创建一个新列表是一个合理的方式来做到这一点(注意列表大小通常在50以下)。
std::list<int> a;
size_t n = 13;
auto end = std::next(a.begin(), std::min(n, a.size()));
使包含第一个列表的前n个元素的新列表:
std::list<int> b(a.begin(), end);
或者填充现有列表:
std::list<int> b;
std::copy(a.begin(), end, std::back_inserter(b));
我看着,我不认为'std :: advance'会照顾到最后。至少这个标准只是让它推进迭代器。它没有提到检查。 – chris 2013-04-09 15:40:44
为什么你不能简单地做'a.begin()+ n'? – 0x499602D2 2013-04-09 15:41:26
@ 0x499602D2,这是一个双向迭代器。无论如何,'std :: next'都可以工作。 – chris 2013-04-09 15:41:41
// list<int> input;
list<int> output;
for (list<int>::const_iterator i = input.begin(); i != input.end() && N > 0; ++i, --N)
output.push_back(*i);
我想没有其他人同意迭代列表两次,当你可以很容易地避免它是这样愚蠢的悲观化。 – 2013-04-09 15:49:28
@BenjaminLindley:你是什么意思?你是说这个比别人好还是不好?其他答案是否会导致列表被迭代两次? – User 2013-04-09 19:06:36
@用户:是的,我的意思是说这个答案可能更有效率,但可能不是太多。其他答案使用'std :: next'来查找用于初始化第二个列表的结束迭代器。对于像'std :: vector'或'std :: deque'这样的容器,这将是一个便宜的操作,因为它们有随机访问迭代器。但对于'std :: list',由于它有双向迭代器,因此它需要遍历列表中的每个项目直到N.然后,当初始化第二个列表时,需要重新迭代。 – 2013-04-09 19:11:22
template<typename T>
std::list<T> first_n(const std::list<T> &in, std::size_t n) {
return std::list<T> out{in.begin(),
std::next(in.begin(), std::min(in.size(), n))};
}
机会是你*不要*为输入*或*结果使用'std :: list'。在大多数情况下,'std :: vector'会使生活变得更简单。大多数算法在定义的范围内工作,这将允许您在正确的子集上进行操作,而无需复制。 – 2013-04-09 15:48:45
@JerryCoffin我需要排序列表之前采取的子集,是否影响使用矢量的决定? – User 2013-04-09 15:54:31
是的 - 它使矢量更好的选择。如果你只想要N个最大(或最小)的项目,你可以使用'std :: nth_element'来获取它们。 – 2013-04-09 16:43:21