不用recursion,不用迴圈,如何只用map消除列表中重複的元素?

時間 2021-05-06 03:15:44

1樓:摺紙

用haskell寫的. 不考慮時間複雜度不用除了提到的任何以外的預設好的函式。

ormap :: (Int->Bool)->[Int]->Boolormap f xs = foldl (\x y->x || f y) False xs

unique' :: [Int]->[Int]unique' = foldl (\arr n->if ormap (==n) arr then arr else n : arr)

flip :: [Int]->[Int]

flip = foldl (\arr n-> n : arr)solution = Main.flip . unique'

2樓:ayanamists

用foldl是很簡單的,

(define

(solve2l)

(reverse

(foldl(λ

(xres)

(if(equal?

(member

xres)#f

)(cons

xres

)res))'

()l)))(

solve2'(

1233

4));'(1 2 3 4)

另外我看還有人用Y、Z combinator來造遞迴,其實倒也不必這樣。

如果你不想要得到乙個【通用的遞迴函式產生器】的話,那所謂的Y、Z combinator都是不需要的,我們只要用這樣的結構就可以得到乙個遞迴函式了:

(define

(rec

func)(

λ(x)

(if (=

x1)1

(* x((

func

func)(

- x1))))))

((rec

rec)10)

;3628800

這樣就可以算出階乘來。

(define

(solve

func)(

λ(l)

(if(null? l)

'()(cons

(car l)

((func

func)(

filter(λ

(x)(

not(equal? x(

carl))))

(cdr

l)))))))

((solve

solve)'

(123

344))

;'(1 2 3 4)

這樣就可以解決題主的問題。

為啥我不喜歡那些combinator呢?因為太繞了,如果你沒有見過上面的結構,直接研究那些東西容易被繞進去。

如果你覺得上面的還是有點繞,那還可以用引用來造遞迴:

(define

(solve3n)

(define

temp10)

(define

(innerx)

(if (=

x0)1

(* x(

temp(-

x1)))))

(set!

temp

inner)(

innern))

(solve310)

;3628800

另外,乙個科研式教學式語言

racket的庫那麼豐富,好歹也算個實用的語言吧,,,

3樓:大衛德劉

(define

(unique

lst)

(foldr

(lambda(e

l)(if

(ormap

(lambda(x

)(equal?xe

))l)l

(consel

)))empty

lst))

本來可以舉報作業題的,但racket喚醒了我大一的記憶所以就答了……這題不存在think out of box的問題, foldl foldr ormap這些,本質上全都是遞迴,這題說不允許遞迴只是不允許顯性遞迴罷了

4樓:黃亮anthony

原以為是乙個難題,結果是乙個作業,BS答題不看題的同志。只用map很難,用foldr很簡單。

foldr和foldl是從列表生成乙個值,map雖然是從列表生成列表,但map很難修改列表的次序。

如果把結果列表看成乙個值,那麼foldr和foldl就很適合。輸入乙個列表a,輸出乙個值b,這個值b也是乙個列表。這裡需要乙個函式f(x, b),決定是否把a的元素x放到b中,根據foldr的定義,f需要返回新的b值。

(define (f

xb)(

if (

member xb

)b(cons xb

)))(

define

(uniquea)

(foldrf'

()a))測試一下

> (unique '(1 2 2 3 3))'(1 2 3)

當然,寫成lambda也可以

(define

(uniquea)

(foldr

(lambda (x

b)(if

(member xb

)b(cons xb

)))'()a

))member也可以用foldr寫,用foldl寫更好。

(define

(member2xa

)(foldr

(lambda (y

b)(or b(

equal? yx

)))#fa))

5樓:

(define

(uniquexs)

(fold-right

(lambda (x

y)(cons x(

filter

(lambda (e

)(not(equal? ex

)))y

)))'

()xs

))>(fold-right

(lambda (x

y)(cons xy

))'()'

(123

45))(

1234

5)>(fold-left

(lambda (x

y)(cons xy

))'()'

(123

45))(((((().1

).2)

.3).

4).5

)>(fold-left

(lambda (x

y)(cons yx

))'()'

(123

45))(

5432

1)>(fold-left

(lambda (x

y)(list yx

))'()'

(123

45))(

5(4(

3(2(

1())))))

>(fold-right

(lambda (x

y)(list xy

))'()'

(123

45))(

1(2(

3(4(

5())))))

都提示用 fold-right 了,很容易理解的。

(define

(uniquexs)

(let*

((member

(lambda (x

xs)(ormap

(lambda (e

)(equal? ex

))xs

)))(

res(

reverse

(cdr

(fold-left

(lambda (x

y)(let

((ls

(car x))

(acc

(cdr

x)))

(if(member yls

)x(cons

(cons yls

)(cons

yacc

)))))

(cons '()

'())

xs)))))

res))

比較常用的 foldl(reduce) 寫到這裡覺得要用 reverse 了就會覺得要利用 foldr 的特性了。

用 Y 的是在開玩笑的吧。欺負小朋友不懂啥是 general recursion?

上面的(filter

(lambda (e

)(not(equal? ex

)))y

)等於 ,但這裡其實只要 (remove first occurrence of x in y)就行了。

(letrec

((rm-fst

(lambda (l

)(if (

null? l)

l(if (

equal? x(

car l))

(cdr l)

(cons

(car l)

(rm-fst

(cdr

l))))))))

(rm-fsty))

但明顯這裡用了 letrec,不合規。

所以可以用 continuation 來在 foldl 中 early return。

(define

(rm-fstea

)(let((res

(call/cc

(lambda (k

)(fold-left

(lambda (x

y)(if(equal? ey

)(k(

cons

(car x)

(cdr

(cdr

x))))

(cons

(lambda (z

)((car x)

(cons yz

)))(

cdr(cdr

x)))))

(cons

(lambda (x

)x)a

)a)))))

((car

res)

(cdr

res))))

(define

(uniquexs)

(fold-right

(lambda (x

y)(cons x(

rm-fstxy

)))'

()xs

))>(rm-fst'a'

(abc

a))(b

ca)>(unique'(

abcc

dcbe

))(ab

cde)

如果要對 gc 友好一點的話(如沒有 x 原樣返回 y),也可以這樣寫

(define

(rm-fstea

)(call/cc

(lambda (k

)(begin

(fold-left

(lambda (x

y)(if(equal? ey

)((car x)

(cdr

(cdr

x)))

(cons

(lambda (z

)((car x)

(cons yz

)))(

cdr(cdr

x)))))

(cons

(lambda (x

)(kx

))a)a

)a))))

6樓:Shangyin Tan

Edit:

remove用fold也很好寫。可以自己試試。

為了防止直接copy我用Scala寫了個錯的答案:

deffoldRight

[A,B

](as

:List[A

],z:B

)(f:(

A,B)

=>B)

:Bdefdistinct[A

](as

:List[A

]):List[A

]=foldRight(as

,Nil

:List[A

])((h,

z)=>if(

exist(h

,z))z

elseh:

:z)defexist[A

](a:A

,res

:List[A

]):Boolean

=foldRight

(res

,false

)((h,b

)=>b||

h==a)

現在問題是這裡返回的List中的element是乙個element最後出現的位置。不過這個可以用foldLeft來解決或者用reverse。這些都可以用foldRight來寫。

7樓:

請審題,是不允許 explicit recursion,是只允許你呼叫裡面的 map/fold 等函式,而 fold 函式的多數實現都是遞迴的,只是題目不讓你用遞迴去思考,要站在稍微高一點的緯度。

稍微看了下 racket 文件,有個 andmap 可以幫你完成去重這件事,我只會 haskell,匿了 orz

Python的for迴圈為什麼不用括號?

紀文光 這個問題很簡單,如果你加了括號和沒加括號實現的效果都沒差別,那麼就不要加括號。類似的問題,Python的if是沒有end if的。這個end if是給計算機看到,人自然語言說話的時候可不會說假設結束。個人認為Python最好的地方就是很貼近自然語言,這樣你更多的精力是放在解決問題上而不是找括...

如何不用迴圈和條件語句列印1到N(假設N為4,排列數就為256)的全排列?

時冰藍 提供個思路,乙個是遞迴,迴圈能做的遞迴都能做.還有乙個,不能用if,但沒說不能判斷邏輯吧?typedef void T Func T Func Funcs 2 代入你想判斷的函式到Funcs 0 和 1 然後你就可以歡快的 Funcs a b 成立嗎? spiritsaway 樓主啊,你的膝...

不用Se Si如何學習?

蘭陵遺風 超低Se Si者飄過,特別是Si,幾乎是沒有的。沒有辦法,學習必須要用S,否則就完蛋。而且對於考試,沒有S永遠得不了高分。別想著抄近路,不存在的。 狹義 通過閱讀 聽講 研究 觀察 理解 探索 實驗 實踐等手段獲得知識或技能的過程,是一種使個體可以得到持續變化 知識和技能,方法與過程,情感...