我一直在尝试编写返回矩阵转置的函数。所以输出的示例是(transpose (list '(1 2) '(4 5))) ;==> ((1 4) (2 5))
这是我的函数:
(define transpose
(lambda (m1)
(if (null? (cadr m1))
null
(list (indiv (car m1) (cadr m1)) (transpose (rest m1))))))
(define indiv
(lambda (l1 l2)
(if (empty? l1)
null
(list (list (car l1) (car l2)) (indiv (rest l1) (rest l2))))))
indiv函数负责行递归,而transpose调用indiv函数来获取转置。我的问题是为什么(if (null? (cadr m1))
没有工作以检查我是否已到达矩阵的最后一行?有没有办法在计划中检查这个?我不想用另一种方法来解决这个问题,我只是想知道这是否可能,如果是,那么如何?
答案 0 :(得分:6)
这是一个相当常见的功能,实现它的通常方法是:
(define (transpose lst)
(apply map list lst))
将lst
视为将作为参数传递给map
的列表列表,并记住map
接受多个输入列表作为参数:
(map list '(1 2) '(4 5))
现在很容易看到发生了什么:我们将list
映射到所有参数,并使用第一个输入列表的第一个元素和第二个输入列表的第一个元素构建子列表,等等。然后,我们将使用第一个输入列表的第二个元素和第二个输入列表的第二个元素等构建一个子列表,依此类推。 map
收集单个输出列表中的所有子列表。你去吧!
'((1 4) (2 5))
答案 1 :(得分:2)
使用map确实可以简化事情。
(define transpose
(lambda (m1)
(if (null? (car m1))
null
(cons (map car m1)
(transpose (map cdr m1))))))
休息通常与cdr相同,并且您不希望这样,您希望将cdr映射到矩阵表示以超过第一行。你很好地完成了这个,但问题是它不能扩展到更大的矩阵。
你不工作的原因是它调用'((1 2)(4 5))的其余部分的转置,即((4 5))其cdr没有车。 (这是空列表),你遇到了一个错误。