刪除元素首次出現在列表中,我可以刪除元素的所有出現在列表中:使用列表理解
*Main> let d = [1, 2, 3, 4, 5, 6]
*Main> d
[1,2,3,4,5,6]
*Main> [x | x <- d, not(x == 2)]
[1,3,4,5,6]
我只是想知道是否有任何可能刪除元素的唯一一次出現在列表中,但使用列表理解?
刪除元素首次出現在列表中,我可以刪除元素的所有出現在列表中:使用列表理解
*Main> let d = [1, 2, 3, 4, 5, 6]
*Main> d
[1,2,3,4,5,6]
*Main> [x | x <- d, not(x == 2)]
[1,3,4,5,6]
我只是想知道是否有任何可能刪除元素的唯一一次出現在列表中,但使用列表理解?
不,沒有。該列表理解
[ x | x <- d, GUARD ]
相當於被定義如下:
let ok x = if GUARD then [x] else []
ok _ = []
in concatMap ok d
通過「如果」的定義,後衛必須是一個純粹的布爾表達式(即單獨評估爲True的假),所以它不能跟蹤狀態,因爲你在列表上映射(假設你要按照規則來玩)。
話雖如此,有一種解決方法使用解析:將狀態壓縮到輸入列表中,並在該組合列表上運行列表理解。這個複合列表可能有一種類似[(Int, Bool)]
的類型,Bool表示這是否是列表中的第一項。然後,您這樣做:
[ x | (x, isFirst) <- zip d (findFirsts d), not (x == 2 && isFirst)]
其中findFirsts d
實施就留給讀者做練習。
但你不想在這種特殊情況下做到這一點。這是一個不好的解決方案,因爲它基本上意味着你至少要經歷兩次這個列表,一次找出哪些項目是第一個,並且一次實際過濾出你不想要的項目。如果你天真地實施了findFirsts
,你可能會看到更多的工作。不適合這份工作!
對於某些問題,例如檢查頭部或將某個項目的特定位置合併到結果中(如hvr已經演示),這可能是一種非常有效的技術。其他
兩種方式:
使用一元計算,攜帶狀態,你依次遍歷列表。如果您想要遍歷任意或複雜的結構,或者計算將變得複雜的情況下,可能會出現問題,但在這種情況下,如果您願意,最好:
只需使用簡單的遞歸函數解決方案,這是Data.List.delete
和deleteBy
做什麼。
下刪除元素只有在發生的歷史頭部位置:
[ x | (i, x) <- zip [0..] d, if i == 0 then x /= 2 else True ]
(這是不是問題)
看起來不起作用:* Main> let d = [1,2,3,4,5,6,2,7,2] * Main> [x | (i,x)< - zip [0 ..] d,not(x == 2)|| i/= 0] [1,2,3,4,5,6,2,7,2] – demas 2011-04-01 06:41:35
對不起,我第一次弄錯了,現在應該修好了 - Doh,還是錯的...現在我終於明白你在做什麼... – hvr 2011-04-01 06:42:11
tbh,在迭代之間用列表理解來傳遞信息是相當麻煩的;你不得不依賴實用函數來爲你做這件事。使用列表理解類似於使用concat/map/filter的組合,其缺乏例如一個摺疊帶來了桌子。 – hvr 2011-04-01 06:48:48
因爲我想指出的記錄,即delete功能在Data.List模塊提供了你描述的行爲。
所以,你可以欺騙了一下,只使用delete在列表理解:
> let l = [1,2,3,2,1]
> [x | x <- delete 2 l]
[1,3,2,1]
我想這不計數。
...所以,我很好奇,如何做到這一點,這裏是不使用delete一個解決方案:
-- Removes the first occurrence of '2' in 'l', if any.
[x | (x,y) <- zip l [0..], let idx = elemIndex 2 l, idx == Nothing || y /= fromJust idx]
的想法是先打開列表轉換成元組的列表,其中第二每個元組的元素是元素的索引,例如"abcba"
變成[('a',0),('b',1),('c',2),('b',3),('a',4)]
。然後,我們將第二個元組元素不等於'elemIndex'返回的值(它返回給定元素的第一個出現位置)的所有元組的每個第一個元素。例如,elemIndex 'b' "abca"
產生2
,所以我們採取第二個元素不是2
的所有元組的第一個元素。那產量"acba"
。
不是直接。列表解析等同於僅使用concat
和map
。他們統一映射元素 - 如果a
更改爲b
(或已刪除或更改爲多個元素),則所有發生的a
都會執行相同操作。
醜陋的方式將標籤與數字內容和搜索的第一個:
f r x = let x' = zip x [0..]
(_,n) = head [v | v <- x', fst v == r]
in [y | (y,m) <- x', y /= r || m /= n]
首先zip
可以用LC表示,如果你使用的擴展名「平行列表理解」。這是非常不自然的,更好地使用顯式遞歸或Data.List.delete
。
我猜想像 [x |不是$ null d,x < - 尾d] 是不是你以後? – hvr 2011-04-01 06:32:33
正如我所看到的,它刪除了列表中的第一個元素,它的作用類似於「尾部d」。但是我需要刪除第一個遇到的號碼(在我的例子中是'2')。 – demas 2011-04-01 06:37:37