简体   繁体   English

从方案中的列表中获取元素

[英]Get element from list in scheme

I need to make a function which returns a element from a list given in a position given.我需要制作一个 function,它从给定的 position 中给出的列表中返回一个元素。 For example the element in third position from this list (2 4 3 5) will be 3.例如,此列表 (2 4 3 5) 中第三个 position 中的元素将为 3。

I have this code but it doesn't run.我有这段代码,但它没有运行。

(define (getElement lst pos)
  (if (= pos 0)
      (car lst))
  (if (> pos 0)
      (getElement (cdr lst) (- pos 1))))

How can I fix this?我怎样才能解决这个问题?

The procedure you're looking for is called list-ref - bear in mind that indexes are zero-based, so the "third" element will be at index 2 .您要查找的过程称为list-ref - 请记住,索引是从零开始的,因此“第三个”元素将位于索引2 For example:例如:

(list-ref '(2 4 3 5) 2)
=> 3

Now, if you want to implement the procedure from scratch you'll have to consider three cases, your current solution is not far from being correct.现在,如果您想从头开始实施该过程,则必须考虑三种情况,您当前的解决方案离正确不远了。 Ask yourself:问你自己:

  • What happens if the list is empty or if the given index is outside the valid range of values for the input list?如果列表为空或给定索引超出输入列表的有效值范围,会发生什么情况? then you must return an appropriate value (say, #f ) or signal an error那么你必须返回一个适当的值(比如#f )或发出错误信号
  • What happens if the current position is zero?如果当前位置为零会发生什么? that means that we found the element, it's the current one这意味着我们找到了元素,它是当前元素
  • Otherwise, keep traversing the list and subtract one from the position否则,继续遍历列表并从位置减一

I'll give you some hints, notice that this is easier to write using a cond instead of nesting if s.我会给你一些提示,请注意,使用cond而不是嵌套if s 更容易编写。 Fill-in the blanks:填空:

(define (getElement lst pos)
  (cond ((null? lst) <???>)
        ((= pos 0) <???>)
        (else (getElement <???> <???>))))

It works just like list-ref :它的工作原理就像list-ref

(getElement '(2 4 3 5) 2)
=> 3

Óscar has the correct solution, I think I just want to point out why you don't get the answer you are looking for. Óscar 有正确的解决方案,我想我只是想指出为什么你没有得到你正在寻找的答案。

Your procedure has two expression in it's body:你的程序在它的主体中有两个表达式:

(define (getElement lst pos)
  expression-1
  expression-2)

Unless you are doing display , define , set!除非你在做displaydefineset! , set-car! set-car! , set-cdr! set-cdr! or any mutable operation expresion-1 won't do anything since it's the result of expression-2 which is the result of the procedure.或者任何可变操作 expresion-1 都不会做任何事情,因为它是expression-2的结果,它是过程的结果。 (tail expression) (尾巴表达)

An if has the following form:一个 if 具有以下形式:

(if predicate-expression
    consequent-expression
    alternative-expression)

Now.现在。 The alternative is optional which means the Scheme implementation will set it to something, perhaps #t .替代方案是可选的,这意味着 Scheme 实现会将其设置为某些内容,可能是#t It doesn't matter.没关系。 Your if would then be:您的 if 将是:

(if (> pos 0)
    (getElement (cdr lst) (- pos 1)))
    'implementation-dependent-alternative-value)

This is the tail and if pos is greater than 0 you will recurse untill it's not and then implementation-dependent-alternative-value will always be the final result.这是尾部,如果pos大于0您将递归直到它不是,然后implementation-dependent-alternative-value将始终是最终结果。 Some implementations don't display their default values so you might noe even see anythign in the REPL.某些实现不显示其默认值,因此您甚至可能看不到 REPL 中的任何内容。

If you assume the list is always larger than the index and that the index always is positive you can just join together the predicate and use the two consequences as consequence and alternative.如果您假设列表始终大于索引并且索引始终为正,则可以将谓词连接在一起并将两个结果用作结果和替代。

;; name change to conform to Scheme naming convention
(define (get-element lst pos) 
  (if (<= pos 0)
      (car lst)
      (get-element (cdr lst) (- pos 1))))

So the rule is: Keep from having more than one statement in you procedure body (only in tail position) except if they do side effects.所以规则是:除非它们有副作用,否则在你的过程体中不要有多个语句(只在尾部位置)。 (ie define local procedures) (即define本地程序)

 ; to retrieve the 'ith' element in a list

 (define ( myGetElement Lst Pos )
    ( if ( null? Lst )       ;if the list is empty 
       ()
       ( if ( = Pos 1 )      
            ( car Lst ) ;the first position of the list
            ( myGetElement ( cdr Lst ) ( - Pos 1 ) )
             ; use recursion to find the next pos
       )
    )
 )

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM