如果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