2013-03-12 126 views
1

這是我現在在做什麼:如何從Vector中刪除元素?

private var accounts = Vector.empty[Account] 

    def removeAccount(account: Account) 
    { 
    accounts = accounts.filterNot(_ == account) 
    } 

是否有一個更可讀的解決方案嗎?理想情況下,我想寫accounts = accounts.remove(account)

+1

如果賬戶存在兩個(或更多)副本,會發生什麼? – paradigmatic 2013-03-12 16:58:31

回答

3

我會使用這樣的:

accounts filterNot account.== 

其內容頗能我,但情況因人而異。我還想要一個不帶謂詞的count,但收集庫實際上缺乏專門的方法,其中有謂詞的人可以推廣這個操作。

直到2.8.x,出現 a -方法,由於語義問題,它被棄用,iirc。如果我的記憶正在爲我服務,它實際上可能會在2.10時回來,但事實並非如此。 編輯:我檢查出來,看到-現在保留爲可變方法,修改它應用的集合。儘管在序列上,我會全都贊成-:/:-,在這種情況下,將第一個或最後一個元素放在某個位置是合理的。任何人都願意爲此付票嗎?我會贊成它。 :-)

4

不幸的是,如果同一帳戶存在兩次,filterNot將刪除它們兩個,但更糟的是(可能)。我可以提供可讀性的唯一的事情就是用

accounts.filter(_ != account) 

另一種可能性是使用確實有刪除操作,如TreeSet(它被稱爲-)集合類型。如果你沒有重複的條目,Set是完全沒問題的。 (當然,這對於某些操作來說比較慢,但它可能更適合應用程序 - 它在移除單個條目時效率更高;使用filterNot,您基本上必須再次構建整個Vector。)

+0

是否有一個不可變的'Set'按照它們插入的順序來組織元素? – fredoverflow 2013-03-12 14:57:51

+1

有'scala.collection.mutable.LinkedHashSet'。 – 2013-03-12 15:06:08

+0

可以訂購'TreeSet',但您必須提供自己的訂購。但事實證明這很尷尬:您需要知道訂購索引才能搜索您的物品。如果它可以成爲「賬戶」的屬性,那麼您的狀態良好。否則很難添加,因爲你需要知道例如一個ID號碼爲了找到你的物品,但你只有物品不是它的ID。 – 2013-03-12 15:12:08

3

您可以使用爲所有序列定義的diff方法。它計算兩個序列之間的多重差異 - 意味着它會根據需要去除儘可能多的元素。

Vector(1, 2, 1, 3, 2).diff(Seq(1)) => 
Vector(2, 1, 3, 2) 

Vector(1, 2, 1, 3, 2).diff(Seq(1, 1)) => 
Vector(2, 3, 2) 

Vector(1, 2, 1, 3, 2).diff(Seq(1, 1, 2)) 
Vector(3, 2) 
3

你可以做這樣的事情:

def removeFirst[T](xs: Vector[T], x: T) = { 
    val i = xs.indexOf(x) 
    if (i == -1) xs else xs.patch(i, Nil, 1) 
} 

然後

accounts = removeFirst(accounts, account) 

我認爲這個問題的要點,不過,是一個Vector可能是不正確的收藏輸入一個設置你想把東西拉出來的東西(提示:嘗試Set)。如果你想索引一個ID或插入索引,那麼Map可能就是你之後(它有一個-方法)。如果你想有效地索引多個東西,你需要一個數據庫!

0

如果您不想使用filterNot閉包,則可以使用更詳細但更明確的for-comprehension樣式。

private var accounts = Vector.empty[Account] 

def removeAccount(account: Account) 
{ 
    accounts = for { a <- accounts 
        if a != account } yield { a } 
} 

這是一個個人喜好的問題,在這種情況下是否感覺更好。

當然,對於涉及嵌套flatMaps等的更復雜表達式,我同意Martin Odersky的建議,即理解可以更容易閱讀,特別是對於新手。