2017-08-21 31 views
4

我要的是這樣的方法:我怎樣才能從鏽蝕的Vec中獲取物品?

fn take<T>(vec: Vec<T>, index: usize) -> Option<T> 

但是,我無法找到這樣的方法。我錯過了什麼嗎?或者是否有一個原因實際上是不安全/不能正確完成的。

編輯:這是從​​3210 有不同的問題的目標是一個remove方法並沒有慌亂的越界進入這裏,我找的是消耗的方法(即,而不是返回的結果。) Vec,並返回其中一個元素。上述問題的答案都沒有解決我的問題。

編輯2:爲了進一步澄清,我正在尋找的是消耗的VEC,並返回一個元素的方法,無需恢復VEC的不變量的方式removeswap_remove做的開銷。

+0

你是指''選項'而不是'選項<&T>',你可以從'vec.get(index)'得到,或者你錯過'.get'存在嗎? – loganfsmyth

+0

@loganfsmyth我特意指'選項'就像我在問題中說的那樣。我想要的是類似於'option.take()'如果這是有道理的? – Others

+0

注意:如果您發現自己定期拋出「Vec」,則可能需要查看是否可以避免實現它們。不管做什麼都比做某事快,無論你做得多高效。 –

回答

7

你可以寫你的函數是這樣的:

fn take<T>(mut vec: Vec<T>, index: usize) -> Option<T> { 
    if vec.get(index).is_none() { 
     None 
    } else { 
     Some(vec.swap_remove(index)) 
    } 
} 

這是保證O(1)。


要使用迭代器提另一種解決方案:

fn take<T>(vec: Vec<T>, index: usize) -> Option<T> { 
    vec.into_iter().nth(index) 
} 

我正要寫:

雖然Iterator::nth()通常是線性時間操作,迭代器上的矢量重寫此方法使其成爲O(1)操作。

但後來我注意到,這只是迭代器迭代片。將在上面的代碼中使用的std::vec::IntoIter迭代器不會覆蓋nth()。它已被嘗試here,但它似乎並不那麼容易。

所以:截至目前,上面的代碼是O(n)操作!

+0

啊,這是一個難看的解決方案,但我認爲它應該工作!我仍然認爲在Vec上採取'take'方法會很好... – Others

+0

@其他也許你應該打開一個RFC – Boiethios

+0

如何在第一個解決方案中將'mut vec:Vec '更改爲'vec:&mut Vec '? – lukwol

1

標準庫中不存在fn take<T>(vec: Vec<T>, index: usize) -> Option<T>的原因,是它一般不是很有用。例如,假設你有一個長度爲10的Vec<String>,這意味着扔掉9個字符串,只使用1。這看起來很浪費。

通常,標準庫將嘗試提供在最大場景中有用的API,在這種情況下,擁有fn take<T>(vec: &mut Vec<T>, index: usize) -> Option<T>會更合乎邏輯。

唯一的問題是如何保持不變,當然:

  • 可以通過最後一個元素,這是什麼Vec::swap_remove做交換被保留,
  • 它可以通過改變被保留後繼元素,這是Vec::drain做什麼。

這些非常靈活,可以適應更多特定場景,比如你的。


適應swap_remove

fn take<T>(mut vec: Vec<T>, index: usize) -> Option<T> { 
    if index < vec.len() { 
     Some(vec.swap_remove(index)) 
    } else { 
     None 
    } 
} 

適應drain

fn take<T>(mut vec: Vec<T>, index: usize) -> Option<T> { 
    if index < vec.len() { 
     vec.drain(index..index+1).next() 
    } else { 
     None 
    } 
} 

注意到,前者是更有效的:它的O(1)。


爲了進一步澄清,我正在尋找消耗的Vec,並返回一個元素的方法,無需恢復Vec的不變量的方式removeswap_remove做的開銷。

這對我來說過早的微觀優化。

首先,請注意,有必要銷燬向量的元素;您可以通過兩種方式實現:

  1. swap_remove,然後每個元素遍歷消滅他們,
  2. 遍歷每個元素來消滅它們,跳過特定index

我不清楚後者會比前者快;如果有任何事情看起來更復雜,更多的分支(我建議兩個循環),這可能會甩掉預測器,並且可能不太適合矢量化。

其次,在抱怨恢復Vec的不變量的開銷之前,你有沒有正確的配置文件的解決方案?

如果我們看一下swap_remove變型中,有3個步驟:

  1. swap_remove(O(1)),
  2. 破壞每個剩餘元素(O(N)),
  3. 自由的後備記憶。

步驟2可以被優化了,如果元素沒有Drop實施,但除此之外,我會它是一個拋是否(2)或(3)佔主導的成本。

TL; DR:恐怕你在拼鬼的問題,配置文件試圖優化之前。

+0

我不一定只抱怨恢復Vec不變量的開銷(儘管我正在使用的代碼是在一個緊密的內部循環中,所以速度對我來說真的很重要),我也想編寫代碼,意思。在這種情況下,我真的想表達'take'操作,而不是'remove'操作。即使這只是一個速度問題,我仍然需要一個替代方案來反正。 – Others

+0

@其他:「緊內環」和「滴'vec'」聽起來不太好。一旦你寫了代碼,我鼓勵你把它發佈到代碼評論或reddit,並詢問如何優化它;希望有一種方法可以避免內部循環中的內存釋放,因爲這些代碼是昂貴的。 –